]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_ast_lowering/src/expr.rs
Add 'compiler/rustc_codegen_cranelift/' from commit '793d26047f994e23415f8f6bb5686ff2...
[rust.git] / compiler / rustc_ast_lowering / src / expr.rs
1 use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs};
2
3 use rustc_ast::attr;
4 use rustc_ast::ptr::P as AstP;
5 use rustc_ast::*;
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;
10 use rustc_hir as hir;
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;
17 use std::fmt::Write;
18
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)))
22     }
23
24     pub(super) fn lower_expr(&mut self, e: &Expr) -> &'hir hir::Expr<'hir> {
25         self.arena.alloc(self.lower_expr_mut(e))
26     }
27
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)
37                 }
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))
42                 }
43                 ExprKind::MethodCall(ref seg, ref args, span) => {
44                     let hir_seg = self.arena.alloc(self.lower_path_segment(
45                         e.span,
46                         seg,
47                         ParamMode::Optional,
48                         0,
49                         ParenthesizedGenericArgs::Err,
50                         ImplTraitContext::disallowed(),
51                         None,
52                     ));
53                     let args = self.lower_exprs(args);
54                     hir::ExprKind::MethodCall(hir_seg, seg.ident.span, args, span)
55                 }
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)
61                 }
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)
66                 }
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)
72                 }
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)
77                 }
78                 ExprKind::AddrOf(k, m, ref ohs) => {
79                     let ohs = self.lower_expr(ohs);
80                     hir::ExprKind::AddrOf(k, m, ohs)
81                 }
82                 ExprKind::Let(ref pat, ref scrutinee) => {
83                     self.lower_expr_let(e.span, pat, scrutinee)
84                 }
85                 ExprKind::If(ref cond, ref then, ref else_opt) => {
86                     self.lower_expr_if(e.span, cond, then, else_opt.as_deref())
87                 }
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)
91                     }),
92                 ExprKind::Loop(ref body, opt_label) => self.with_loop_scope(e.id, |this| {
93                     hir::ExprKind::Loop(
94                         this.lower_block(body, false),
95                         opt_label,
96                         hir::LoopSource::Loop,
97                     )
98                 }),
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,
104                 ),
105                 ExprKind::Async(capture_clause, closure_node_id, ref block) => self
106                     .make_async_expr(
107                         capture_clause,
108                         closure_node_id,
109                         None,
110                         block.span,
111                         hir::AsyncGeneratorKind::Block,
112                         |this| this.with_new_scopes(|this| this.lower_block_expr(block)),
113                     ),
114                 ExprKind::Await(ref expr) => self.lower_expr_await(e.span, expr),
115                 ExprKind::Closure(
116                     capture_clause,
117                     asyncness,
118                     movability,
119                     ref decl,
120                     ref body,
121                     fn_decl_span,
122                 ) => {
123                     if let Async::Yes { closure_id, .. } = asyncness {
124                         self.lower_expr_async_closure(
125                             capture_clause,
126                             closure_id,
127                             decl,
128                             body,
129                             fn_decl_span,
130                         )
131                     } else {
132                         self.lower_expr_closure(
133                             capture_clause,
134                             movability,
135                             decl,
136                             body,
137                             fn_decl_span,
138                         )
139                     }
140                 }
141                 ExprKind::Block(ref blk, opt_label) => {
142                     hir::ExprKind::Block(self.lower_block(blk, opt_label.is_some()), opt_label)
143                 }
144                 ExprKind::Assign(ref el, ref er, span) => {
145                     hir::ExprKind::Assign(self.lower_expr(el), self.lower_expr(er), span)
146                 }
147                 ExprKind::AssignOp(op, ref el, ref er) => hir::ExprKind::AssignOp(
148                     self.lower_binop(op),
149                     self.lower_expr(el),
150                     self.lower_expr(er),
151                 ),
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))
155                 }
156                 ExprKind::Range(Some(ref e1), Some(ref e2), RangeLimits::Closed) => {
157                     self.lower_expr_range_closed(e.span, e1, e2)
158                 }
159                 ExprKind::Range(ref e1, ref e2, lims) => {
160                     self.lower_expr_range(e.span, e1.as_deref(), e2.as_deref(), lims)
161                 }
162                 ExprKind::Path(ref qself, ref path) => {
163                     let qpath = self.lower_qpath(
164                         e.id,
165                         qself,
166                         path,
167                         ParamMode::Optional,
168                         ImplTraitContext::disallowed(),
169                     );
170                     hir::ExprKind::Path(qpath)
171                 }
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)
175                 }
176                 ExprKind::Continue(opt_label) => {
177                     hir::ExprKind::Continue(self.lower_jump_destination(e.id, opt_label))
178                 }
179                 ExprKind::Ret(ref e) => {
180                     let e = e.as_ref().map(|x| self.lower_expr(x));
181                     hir::ExprKind::Ret(e)
182                 }
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(
189                             e.id,
190                             &None,
191                             path,
192                             ParamMode::Optional,
193                             ImplTraitContext::disallowed(),
194                         )),
195                         self.arena.alloc_from_iter(fields.iter().map(|x| self.lower_field(x))),
196                         maybe_expr,
197                     )
198                 }
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) {
206                         ex.span = e.span;
207                     }
208                     // Merge attributes into the inner expression.
209                     let mut attrs = e.attrs.clone();
210                     attrs.extend::<Vec<_>>(ex.attrs.into());
211                     ex.attrs = attrs;
212                     return ex;
213                 }
214
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);
219                 }
220                 ExprKind::MacCall(_) => panic!("{:?} shouldn't exist here", e.span),
221             };
222
223             hir::Expr {
224                 hir_id: self.lower_node_id(e.id),
225                 kind,
226                 span: e.span,
227                 attrs: e.attrs.iter().map(|a| self.lower_attr(a)).collect::<Vec<_>>().into(),
228             }
229         })
230     }
231
232     fn lower_unop(&mut self, u: UnOp) -> hir::UnOp {
233         match u {
234             UnOp::Deref => hir::UnOp::UnDeref,
235             UnOp::Not => hir::UnOp::UnNot,
236             UnOp::Neg => hir::UnOp::UnNeg,
237         }
238     }
239
240     fn lower_binop(&mut self, b: BinOp) -> hir::BinOp {
241         Spanned {
242             node: match b.node {
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,
261             },
262             span: b.span,
263         }
264     }
265
266     /// Emit an error and lower `ast::ExprKind::Let(pat, scrutinee)` into:
267     /// ```rust
268     /// match scrutinee { pats => true, _ => false }
269     /// ```
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.
272
273         if self.sess.opts.unstable_features.is_nightly_build() {
274             self.sess
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")
278                 .emit();
279         } else {
280             self.sess
281                 .struct_span_err(span, "expected expression, found statement (`let`)")
282                 .note("variable declaration using `let` is a statement")
283                 .emit();
284         }
285
286         // For better recovery, we emit:
287         // ```
288         // match scrutinee { pat => true, _ => false }
289         // ```
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);
296         let then_arm = {
297             let pat = self.lower_pat(pat);
298             let expr = self.expr_bool(span, true);
299             self.arm(pat, expr)
300         };
301         let else_arm = {
302             let pat = self.pat_wild(span);
303             let expr = self.expr_bool(span, false);
304             self.arm(pat, expr)
305         };
306         hir::ExprKind::Match(
307             scrutinee,
308             arena_vec![self; then_arm, else_arm],
309             hir::MatchSource::Normal,
310         )
311     }
312
313     fn lower_expr_if(
314         &mut self,
315         span: Span,
316         cond: &Expr,
317         then: &Block,
318         else_opt: Option<&Expr>,
319     ) -> hir::ExprKind<'hir> {
320         // FIXME(#53667): handle lowering of && and parens.
321
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),
327         };
328         let else_arm = self.arm(else_pat, else_expr);
329
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 })
338             }
339             // `true => <then>`:
340             _ => {
341                 // Lower condition:
342                 let cond = self.lower_expr(cond);
343                 let span_block =
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 })
351             }
352         };
353         let then_arm = self.arm(then_pat, self.arena.alloc(then_expr));
354
355         hir::ExprKind::Match(scrutinee, arena_vec![self; then_arm, else_arm], desugar)
356     }
357
358     fn lower_expr_while_in_loop_scope(
359         &mut self,
360         span: Span,
361         cond: &Expr,
362         body: &Block,
363         opt_label: Option<Label>,
364     ) -> hir::ExprKind<'hir> {
365         // FIXME(#53667): handle lowering of && and parens.
366
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.
369
370         // `_ => break`:
371         let else_arm = {
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)
375         };
376
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) => {
381                 // to:
382                 //
383                 //   [opt_ident]: loop {
384                 //     match <sub_expr> {
385                 //       <pat> => <body>,
386                 //       _ => break
387                 //     }
388                 //   }
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)
392             }
393             _ => {
394                 // We desugar: `'label: while $cond $body` into:
395                 //
396                 // ```
397                 // 'label: loop {
398                 //     match drop-temps { $cond } {
399                 //         true => $body,
400                 //         _ => break,
401                 //     }
402                 // }
403                 // ```
404
405                 // Lower condition:
406                 let cond = self.with_loop_condition_scope(|this| this.lower_expr(cond));
407                 let span_block =
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());
413                 // `true => <then>`:
414                 let pat = self.pat_bool(span, true);
415                 (pat, cond, hir::MatchSource::WhileDesugar, hir::LoopSource::While)
416             }
417         };
418         let then_arm = self.arm(then_pat, self.arena.alloc(then_expr));
419
420         // `match <scrutinee> { ... }`
421         let match_expr =
422             self.expr_match(span, scrutinee, arena_vec![self; then_arm, else_arm], desugar);
423
424         // `[opt_ident]: loop { ... }`
425         hir::ExprKind::Loop(self.block_expr(self.arena.alloc(match_expr)), opt_label, source)
426     }
427
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);
434
435             // Final expression of the block (if present) or `()` with span at the end of block
436             let (try_span, tail_expr) = if let Some(expr) = block.expr.take() {
437                 (
438                     this.mark_span_with_reason(
439                         DesugaringKind::TryBlock,
440                         expr.span,
441                         this.allow_try_trait.clone(),
442                     ),
443                     expr,
444                 )
445             } else {
446                 let try_span = this.mark_span_with_reason(
447                     DesugaringKind::TryBlock,
448                     this.sess.source_map().end_point(body.span),
449                     this.allow_try_trait.clone(),
450                 );
451
452                 (try_span, this.expr_unit(try_span))
453             };
454
455             let ok_wrapped_span =
456                 this.mark_span_with_reason(DesugaringKind::TryBlock, tail_expr.span, None);
457
458             // `::std::ops::Try::from_ok($tail_expr)`
459             block.expr = Some(this.wrap_in_try_constructor(
460                 hir::LangItem::TryFromOk,
461                 try_span,
462                 tail_expr,
463                 ok_wrapped_span,
464             ));
465
466             hir::ExprKind::Block(this.arena.alloc(block), None)
467         })
468     }
469
470     fn wrap_in_try_constructor(
471         &mut self,
472         lang_item: hir::LangItem,
473         method_span: Span,
474         expr: &'hir hir::Expr<'hir>,
475         overall_span: Span,
476     ) -> &'hir hir::Expr<'hir> {
477         let constructor =
478             self.arena.alloc(self.expr_lang_item_path(method_span, lang_item, ThinVec::new()));
479         self.expr_call(overall_span, constructor, std::slice::from_ref(expr))
480     }
481
482     fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> {
483         hir::Arm {
484             hir_id: self.next_id(),
485             attrs: self.lower_attrs(&arm.attrs),
486             pat: self.lower_pat(&arm.pat),
487             guard: match arm.guard {
488                 Some(ref x) => Some(hir::Guard::If(self.lower_expr(x))),
489                 _ => None,
490             },
491             body: self.lower_expr(&arm.body),
492             span: arm.span,
493         }
494     }
495
496     /// Lower an `async` construct to a generator that is then wrapped so it implements `Future`.
497     ///
498     /// This results in:
499     ///
500     /// ```text
501     /// std::future::from_generator(static move? |_task_context| -> <ret_ty> {
502     ///     <body>
503     /// })
504     /// ```
505     pub(super) fn make_async_expr(
506         &mut self,
507         capture_clause: CaptureBy,
508         closure_node_id: NodeId,
509         ret_ty: Option<AstP<Ty>>,
510         span: Span,
511         async_gen_kind: hir::AsyncGeneratorKind,
512         body: impl FnOnce(&mut Self) -> hir::Expr<'hir>,
513     ) -> hir::ExprKind<'hir> {
514         let output = match ret_ty {
515             Some(ty) => hir::FnRetTy::Return(self.lower_ty(&ty, ImplTraitContext::disallowed())),
516             None => hir::FnRetTy::DefaultReturn(span),
517         };
518
519         // Resume argument type. We let the compiler infer this to simplify the lowering. It is
520         // fully constrained by `future::from_generator`.
521         let input_ty = hir::Ty { hir_id: self.next_id(), kind: hir::TyKind::Infer, span };
522
523         // The closure/generator `FnDecl` takes a single (resume) argument of type `input_ty`.
524         let decl = self.arena.alloc(hir::FnDecl {
525             inputs: arena_vec![self; input_ty],
526             output,
527             c_variadic: false,
528             implicit_self: hir::ImplicitSelfKind::None,
529         });
530
531         // Lower the argument pattern/ident. The ident is used again in the `.await` lowering.
532         let (pat, task_context_hid) = self.pat_ident_binding_mode(
533             span,
534             Ident::with_dummy_span(sym::_task_context),
535             hir::BindingAnnotation::Mutable,
536         );
537         let param = hir::Param { attrs: &[], hir_id: self.next_id(), pat, ty_span: span, span };
538         let params = arena_vec![self; param];
539
540         let body_id = self.lower_body(move |this| {
541             this.generator_kind = Some(hir::GeneratorKind::Async(async_gen_kind));
542
543             let old_ctx = this.task_context;
544             this.task_context = Some(task_context_hid);
545             let res = body(this);
546             this.task_context = old_ctx;
547             (params, res)
548         });
549
550         // `static |_task_context| -> <ret_ty> { body }`:
551         let generator_kind = hir::ExprKind::Closure(
552             capture_clause,
553             decl,
554             body_id,
555             span,
556             Some(hir::Movability::Static),
557         );
558         let generator = hir::Expr {
559             hir_id: self.lower_node_id(closure_node_id),
560             kind: generator_kind,
561             span,
562             attrs: ThinVec::new(),
563         };
564
565         // `future::from_generator`:
566         let unstable_span =
567             self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone());
568         let gen_future =
569             self.expr_lang_item_path(unstable_span, hir::LangItem::FromGenerator, ThinVec::new());
570
571         // `future::from_generator(generator)`:
572         hir::ExprKind::Call(self.arena.alloc(gen_future), arena_vec![self; generator])
573     }
574
575     /// Desugar `<expr>.await` into:
576     /// ```rust
577     /// match <expr> {
578     ///     mut pinned => loop {
579     ///         match unsafe { ::std::future::Future::poll(
580     ///             <::std::pin::Pin>::new_unchecked(&mut pinned),
581     ///             ::std::future::get_context(task_context),
582     ///         ) } {
583     ///             ::std::task::Poll::Ready(result) => break result,
584     ///             ::std::task::Poll::Pending => {}
585     ///         }
586     ///         task_context = yield ();
587     ///     }
588     /// }
589     /// ```
590     fn lower_expr_await(&mut self, await_span: Span, expr: &Expr) -> hir::ExprKind<'hir> {
591         match self.generator_kind {
592             Some(hir::GeneratorKind::Async(_)) => {}
593             Some(hir::GeneratorKind::Gen) | None => {
594                 let mut err = struct_span_err!(
595                     self.sess,
596                     await_span,
597                     E0728,
598                     "`await` is only allowed inside `async` functions and blocks"
599                 );
600                 err.span_label(await_span, "only allowed inside `async` functions and blocks");
601                 if let Some(item_sp) = self.current_item {
602                     err.span_label(item_sp, "this is not `async`");
603                 }
604                 err.emit();
605             }
606         }
607         let span = self.mark_span_with_reason(DesugaringKind::Await, await_span, None);
608         let gen_future_span = self.mark_span_with_reason(
609             DesugaringKind::Await,
610             await_span,
611             self.allow_gen_future.clone(),
612         );
613         let expr = self.lower_expr(expr);
614
615         let pinned_ident = Ident::with_dummy_span(sym::pinned);
616         let (pinned_pat, pinned_pat_hid) =
617             self.pat_ident_binding_mode(span, pinned_ident, hir::BindingAnnotation::Mutable);
618
619         let task_context_ident = Ident::with_dummy_span(sym::_task_context);
620
621         // unsafe {
622         //     ::std::future::Future::poll(
623         //         ::std::pin::Pin::new_unchecked(&mut pinned),
624         //         ::std::future::get_context(task_context),
625         //     )
626         // }
627         let poll_expr = {
628             let pinned = self.expr_ident(span, pinned_ident, pinned_pat_hid);
629             let ref_mut_pinned = self.expr_mut_addr_of(span, pinned);
630             let task_context = if let Some(task_context_hid) = self.task_context {
631                 self.expr_ident_mut(span, task_context_ident, task_context_hid)
632             } else {
633                 // Use of `await` outside of an async context, we cannot use `task_context` here.
634                 self.expr_err(span)
635             };
636             let new_unchecked = self.expr_call_lang_item_fn_mut(
637                 span,
638                 hir::LangItem::PinNewUnchecked,
639                 arena_vec![self; ref_mut_pinned],
640             );
641             let get_context = self.expr_call_lang_item_fn_mut(
642                 gen_future_span,
643                 hir::LangItem::GetContext,
644                 arena_vec![self; task_context],
645             );
646             let call = self.expr_call_lang_item_fn(
647                 span,
648                 hir::LangItem::FuturePoll,
649                 arena_vec![self; new_unchecked, get_context],
650             );
651             self.arena.alloc(self.expr_unsafe(call))
652         };
653
654         // `::std::task::Poll::Ready(result) => break result`
655         let loop_node_id = self.resolver.next_node_id();
656         let loop_hir_id = self.lower_node_id(loop_node_id);
657         let ready_arm = {
658             let x_ident = Ident::with_dummy_span(sym::result);
659             let (x_pat, x_pat_hid) = self.pat_ident(span, x_ident);
660             let x_expr = self.expr_ident(span, x_ident, x_pat_hid);
661             let ready_field = self.single_pat_field(span, x_pat);
662             let ready_pat = self.pat_lang_item_variant(span, hir::LangItem::PollReady, ready_field);
663             let break_x = self.with_loop_scope(loop_node_id, move |this| {
664                 let expr_break =
665                     hir::ExprKind::Break(this.lower_loop_destination(None), Some(x_expr));
666                 this.arena.alloc(this.expr(await_span, expr_break, ThinVec::new()))
667             });
668             self.arm(ready_pat, break_x)
669         };
670
671         // `::std::task::Poll::Pending => {}`
672         let pending_arm = {
673             let pending_pat = self.pat_lang_item_variant(span, hir::LangItem::PollPending, &[]);
674             let empty_block = self.expr_block_empty(span);
675             self.arm(pending_pat, empty_block)
676         };
677
678         let inner_match_stmt = {
679             let match_expr = self.expr_match(
680                 span,
681                 poll_expr,
682                 arena_vec![self; ready_arm, pending_arm],
683                 hir::MatchSource::AwaitDesugar,
684             );
685             self.stmt_expr(span, match_expr)
686         };
687
688         // task_context = yield ();
689         let yield_stmt = {
690             let unit = self.expr_unit(span);
691             let yield_expr = self.expr(
692                 span,
693                 hir::ExprKind::Yield(unit, hir::YieldSource::Await { expr: Some(expr.hir_id) }),
694                 ThinVec::new(),
695             );
696             let yield_expr = self.arena.alloc(yield_expr);
697
698             if let Some(task_context_hid) = self.task_context {
699                 let lhs = self.expr_ident(span, task_context_ident, task_context_hid);
700                 let assign =
701                     self.expr(span, hir::ExprKind::Assign(lhs, yield_expr, span), AttrVec::new());
702                 self.stmt_expr(span, assign)
703             } else {
704                 // Use of `await` outside of an async context. Return `yield_expr` so that we can
705                 // proceed with type checking.
706                 self.stmt(span, hir::StmtKind::Semi(yield_expr))
707             }
708         };
709
710         let loop_block = self.block_all(span, arena_vec![self; inner_match_stmt, yield_stmt], None);
711
712         // loop { .. }
713         let loop_expr = self.arena.alloc(hir::Expr {
714             hir_id: loop_hir_id,
715             kind: hir::ExprKind::Loop(loop_block, None, hir::LoopSource::Loop),
716             span,
717             attrs: ThinVec::new(),
718         });
719
720         // mut pinned => loop { ... }
721         let pinned_arm = self.arm(pinned_pat, loop_expr);
722
723         // match <expr> {
724         //     mut pinned => loop { .. }
725         // }
726         hir::ExprKind::Match(expr, arena_vec![self; pinned_arm], hir::MatchSource::AwaitDesugar)
727     }
728
729     fn lower_expr_closure(
730         &mut self,
731         capture_clause: CaptureBy,
732         movability: Movability,
733         decl: &FnDecl,
734         body: &Expr,
735         fn_decl_span: Span,
736     ) -> hir::ExprKind<'hir> {
737         // Lower outside new scope to preserve `is_in_loop_condition`.
738         let fn_decl = self.lower_fn_decl(decl, None, false, None);
739
740         self.with_new_scopes(move |this| {
741             let prev = this.current_item;
742             this.current_item = Some(fn_decl_span);
743             let mut generator_kind = None;
744             let body_id = this.lower_fn_body(decl, |this| {
745                 let e = this.lower_expr_mut(body);
746                 generator_kind = this.generator_kind;
747                 e
748             });
749             let generator_option =
750                 this.generator_movability_for_fn(&decl, fn_decl_span, generator_kind, movability);
751             this.current_item = prev;
752             hir::ExprKind::Closure(capture_clause, fn_decl, body_id, fn_decl_span, generator_option)
753         })
754     }
755
756     fn generator_movability_for_fn(
757         &mut self,
758         decl: &FnDecl,
759         fn_decl_span: Span,
760         generator_kind: Option<hir::GeneratorKind>,
761         movability: Movability,
762     ) -> Option<hir::Movability> {
763         match generator_kind {
764             Some(hir::GeneratorKind::Gen) => {
765                 if decl.inputs.len() > 1 {
766                     struct_span_err!(
767                         self.sess,
768                         fn_decl_span,
769                         E0628,
770                         "too many parameters for a generator (expected 0 or 1 parameters)"
771                     )
772                     .emit();
773                 }
774                 Some(movability)
775             }
776             Some(hir::GeneratorKind::Async(_)) => {
777                 panic!("non-`async` closure body turned `async` during lowering");
778             }
779             None => {
780                 if movability == Movability::Static {
781                     struct_span_err!(self.sess, fn_decl_span, E0697, "closures cannot be static")
782                         .emit();
783                 }
784                 None
785             }
786         }
787     }
788
789     fn lower_expr_async_closure(
790         &mut self,
791         capture_clause: CaptureBy,
792         closure_id: NodeId,
793         decl: &FnDecl,
794         body: &Expr,
795         fn_decl_span: Span,
796     ) -> hir::ExprKind<'hir> {
797         let outer_decl =
798             FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) };
799         // We need to lower the declaration outside the new scope, because we
800         // have to conserve the state of being inside a loop condition for the
801         // closure argument types.
802         let fn_decl = self.lower_fn_decl(&outer_decl, None, false, None);
803
804         self.with_new_scopes(move |this| {
805             // FIXME(cramertj): allow `async` non-`move` closures with arguments.
806             if capture_clause == CaptureBy::Ref && !decl.inputs.is_empty() {
807                 struct_span_err!(
808                     this.sess,
809                     fn_decl_span,
810                     E0708,
811                     "`async` non-`move` closures with parameters are not currently supported",
812                 )
813                 .help(
814                     "consider using `let` statements to manually capture \
815                     variables by reference before entering an `async move` closure",
816                 )
817                 .emit();
818             }
819
820             // Transform `async |x: u8| -> X { ... }` into
821             // `|x: u8| future_from_generator(|| -> X { ... })`.
822             let body_id = this.lower_fn_body(&outer_decl, |this| {
823                 let async_ret_ty =
824                     if let FnRetTy::Ty(ty) = &decl.output { Some(ty.clone()) } else { None };
825                 let async_body = this.make_async_expr(
826                     capture_clause,
827                     closure_id,
828                     async_ret_ty,
829                     body.span,
830                     hir::AsyncGeneratorKind::Closure,
831                     |this| this.with_new_scopes(|this| this.lower_expr_mut(body)),
832                 );
833                 this.expr(fn_decl_span, async_body, ThinVec::new())
834             });
835             hir::ExprKind::Closure(capture_clause, fn_decl, body_id, fn_decl_span, None)
836         })
837     }
838
839     /// Desugar `<start>..=<end>` into `std::ops::RangeInclusive::new(<start>, <end>)`.
840     fn lower_expr_range_closed(&mut self, span: Span, e1: &Expr, e2: &Expr) -> hir::ExprKind<'hir> {
841         let e1 = self.lower_expr_mut(e1);
842         let e2 = self.lower_expr_mut(e2);
843         let fn_path = hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, span);
844         let fn_expr =
845             self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path), ThinVec::new()));
846         hir::ExprKind::Call(fn_expr, arena_vec![self; e1, e2])
847     }
848
849     fn lower_expr_range(
850         &mut self,
851         span: Span,
852         e1: Option<&Expr>,
853         e2: Option<&Expr>,
854         lims: RangeLimits,
855     ) -> hir::ExprKind<'hir> {
856         use rustc_ast::RangeLimits::*;
857
858         let lang_item = match (e1, e2, lims) {
859             (None, None, HalfOpen) => hir::LangItem::RangeFull,
860             (Some(..), None, HalfOpen) => hir::LangItem::RangeFrom,
861             (None, Some(..), HalfOpen) => hir::LangItem::RangeTo,
862             (Some(..), Some(..), HalfOpen) => hir::LangItem::Range,
863             (None, Some(..), Closed) => hir::LangItem::RangeToInclusive,
864             (Some(..), Some(..), Closed) => unreachable!(),
865             (_, None, Closed) => {
866                 self.diagnostic().span_fatal(span, "inclusive range with no end").raise()
867             }
868         };
869
870         let fields = self.arena.alloc_from_iter(
871             e1.iter().map(|e| ("start", e)).chain(e2.iter().map(|e| ("end", e))).map(|(s, e)| {
872                 let expr = self.lower_expr(&e);
873                 let ident = Ident::new(Symbol::intern(s), e.span);
874                 self.field(ident, expr, e.span)
875             }),
876         );
877
878         hir::ExprKind::Struct(self.arena.alloc(hir::QPath::LangItem(lang_item, span)), fields, None)
879     }
880
881     fn lower_loop_destination(&mut self, destination: Option<(NodeId, Label)>) -> hir::Destination {
882         let target_id = match destination {
883             Some((id, _)) => {
884                 if let Some(loop_id) = self.resolver.get_label_res(id) {
885                     Ok(self.lower_node_id(loop_id))
886                 } else {
887                     Err(hir::LoopIdError::UnresolvedLabel)
888                 }
889             }
890             None => self
891                 .loop_scopes
892                 .last()
893                 .cloned()
894                 .map(|id| Ok(self.lower_node_id(id)))
895                 .unwrap_or(Err(hir::LoopIdError::OutsideLoopScope)),
896         };
897         hir::Destination { label: destination.map(|(_, label)| label), target_id }
898     }
899
900     fn lower_jump_destination(&mut self, id: NodeId, opt_label: Option<Label>) -> hir::Destination {
901         if self.is_in_loop_condition && opt_label.is_none() {
902             hir::Destination {
903                 label: None,
904                 target_id: Err(hir::LoopIdError::UnlabeledCfInWhileCondition),
905             }
906         } else {
907             self.lower_loop_destination(opt_label.map(|label| (id, label)))
908         }
909     }
910
911     fn with_catch_scope<T>(&mut self, catch_id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T {
912         let len = self.catch_scopes.len();
913         self.catch_scopes.push(catch_id);
914
915         let result = f(self);
916         assert_eq!(
917             len + 1,
918             self.catch_scopes.len(),
919             "catch scopes should be added and removed in stack order"
920         );
921
922         self.catch_scopes.pop().unwrap();
923
924         result
925     }
926
927     fn with_loop_scope<T>(&mut self, loop_id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T {
928         // We're no longer in the base loop's condition; we're in another loop.
929         let was_in_loop_condition = self.is_in_loop_condition;
930         self.is_in_loop_condition = false;
931
932         let len = self.loop_scopes.len();
933         self.loop_scopes.push(loop_id);
934
935         let result = f(self);
936         assert_eq!(
937             len + 1,
938             self.loop_scopes.len(),
939             "loop scopes should be added and removed in stack order"
940         );
941
942         self.loop_scopes.pop().unwrap();
943
944         self.is_in_loop_condition = was_in_loop_condition;
945
946         result
947     }
948
949     fn with_loop_condition_scope<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T {
950         let was_in_loop_condition = self.is_in_loop_condition;
951         self.is_in_loop_condition = true;
952
953         let result = f(self);
954
955         self.is_in_loop_condition = was_in_loop_condition;
956
957         result
958     }
959
960     fn lower_expr_asm(&mut self, sp: Span, asm: &InlineAsm) -> hir::ExprKind<'hir> {
961         if self.sess.asm_arch.is_none() {
962             struct_span_err!(self.sess, sp, E0472, "asm! is unsupported on this target").emit();
963         }
964         if asm.options.contains(InlineAsmOptions::ATT_SYNTAX)
965             && !matches!(
966                 self.sess.asm_arch,
967                 Some(asm::InlineAsmArch::X86 | asm::InlineAsmArch::X86_64)
968             )
969         {
970             self.sess
971                 .struct_span_err(sp, "the `att_syntax` option is only supported on x86")
972                 .emit();
973         }
974
975         // Lower operands to HIR, filter_map skips any operands with invalid
976         // register classes.
977         let sess = self.sess;
978         let operands: Vec<_> = asm
979             .operands
980             .iter()
981             .filter_map(|(op, op_sp)| {
982                 let lower_reg = |reg| {
983                     Some(match reg {
984                         InlineAsmRegOrRegClass::Reg(s) => asm::InlineAsmRegOrRegClass::Reg(
985                             asm::InlineAsmReg::parse(
986                                 sess.asm_arch?,
987                                 |feature| sess.target_features.contains(&Symbol::intern(feature)),
988                                 &sess.target.target,
989                                 s,
990                             )
991                             .map_err(|e| {
992                                 let msg = format!("invalid register `{}`: {}", s.as_str(), e);
993                                 sess.struct_span_err(*op_sp, &msg).emit();
994                             })
995                             .ok()?,
996                         ),
997                         InlineAsmRegOrRegClass::RegClass(s) => {
998                             asm::InlineAsmRegOrRegClass::RegClass(
999                                 asm::InlineAsmRegClass::parse(sess.asm_arch?, s)
1000                                     .map_err(|e| {
1001                                         let msg = format!(
1002                                             "invalid register class `{}`: {}",
1003                                             s.as_str(),
1004                                             e
1005                                         );
1006                                         sess.struct_span_err(*op_sp, &msg).emit();
1007                                     })
1008                                     .ok()?,
1009                             )
1010                         }
1011                     })
1012                 };
1013
1014                 // lower_reg is executed last because we need to lower all
1015                 // sub-expressions even if we throw them away later.
1016                 let op = match *op {
1017                     InlineAsmOperand::In { reg, ref expr } => hir::InlineAsmOperand::In {
1018                         expr: self.lower_expr_mut(expr),
1019                         reg: lower_reg(reg)?,
1020                     },
1021                     InlineAsmOperand::Out { reg, late, ref expr } => hir::InlineAsmOperand::Out {
1022                         late,
1023                         expr: expr.as_ref().map(|expr| self.lower_expr_mut(expr)),
1024                         reg: lower_reg(reg)?,
1025                     },
1026                     InlineAsmOperand::InOut { reg, late, ref expr } => {
1027                         hir::InlineAsmOperand::InOut {
1028                             late,
1029                             expr: self.lower_expr_mut(expr),
1030                             reg: lower_reg(reg)?,
1031                         }
1032                     }
1033                     InlineAsmOperand::SplitInOut { reg, late, ref in_expr, ref out_expr } => {
1034                         hir::InlineAsmOperand::SplitInOut {
1035                             late,
1036                             in_expr: self.lower_expr_mut(in_expr),
1037                             out_expr: out_expr.as_ref().map(|expr| self.lower_expr_mut(expr)),
1038                             reg: lower_reg(reg)?,
1039                         }
1040                     }
1041                     InlineAsmOperand::Const { ref expr } => {
1042                         hir::InlineAsmOperand::Const { expr: self.lower_expr_mut(expr) }
1043                     }
1044                     InlineAsmOperand::Sym { ref expr } => {
1045                         hir::InlineAsmOperand::Sym { expr: self.lower_expr_mut(expr) }
1046                     }
1047                 };
1048                 Some(op)
1049             })
1050             .collect();
1051
1052         // Stop if there were any errors when lowering the register classes
1053         if operands.len() != asm.operands.len() || sess.asm_arch.is_none() {
1054             return hir::ExprKind::Err;
1055         }
1056
1057         // Validate template modifiers against the register classes for the operands
1058         let asm_arch = sess.asm_arch.unwrap();
1059         for p in &asm.template {
1060             if let InlineAsmTemplatePiece::Placeholder {
1061                 operand_idx,
1062                 modifier: Some(modifier),
1063                 span: placeholder_span,
1064             } = *p
1065             {
1066                 let op_sp = asm.operands[operand_idx].1;
1067                 match &operands[operand_idx] {
1068                     hir::InlineAsmOperand::In { reg, .. }
1069                     | hir::InlineAsmOperand::Out { reg, .. }
1070                     | hir::InlineAsmOperand::InOut { reg, .. }
1071                     | hir::InlineAsmOperand::SplitInOut { reg, .. } => {
1072                         let class = reg.reg_class();
1073                         let valid_modifiers = class.valid_modifiers(asm_arch);
1074                         if !valid_modifiers.contains(&modifier) {
1075                             let mut err = sess.struct_span_err(
1076                                 placeholder_span,
1077                                 "invalid asm template modifier for this register class",
1078                             );
1079                             err.span_label(placeholder_span, "template modifier");
1080                             err.span_label(op_sp, "argument");
1081                             if !valid_modifiers.is_empty() {
1082                                 let mut mods = format!("`{}`", valid_modifiers[0]);
1083                                 for m in &valid_modifiers[1..] {
1084                                     let _ = write!(mods, ", `{}`", m);
1085                                 }
1086                                 err.note(&format!(
1087                                     "the `{}` register class supports \
1088                                      the following template modifiers: {}",
1089                                     class.name(),
1090                                     mods
1091                                 ));
1092                             } else {
1093                                 err.note(&format!(
1094                                     "the `{}` register class does not support template modifiers",
1095                                     class.name()
1096                                 ));
1097                             }
1098                             err.emit();
1099                         }
1100                     }
1101                     hir::InlineAsmOperand::Const { .. } => {
1102                         let mut err = sess.struct_span_err(
1103                             placeholder_span,
1104                             "asm template modifiers are not allowed for `const` arguments",
1105                         );
1106                         err.span_label(placeholder_span, "template modifier");
1107                         err.span_label(op_sp, "argument");
1108                         err.emit();
1109                     }
1110                     hir::InlineAsmOperand::Sym { .. } => {
1111                         let mut err = sess.struct_span_err(
1112                             placeholder_span,
1113                             "asm template modifiers are not allowed for `sym` arguments",
1114                         );
1115                         err.span_label(placeholder_span, "template modifier");
1116                         err.span_label(op_sp, "argument");
1117                         err.emit();
1118                     }
1119                 }
1120             }
1121         }
1122
1123         let mut used_input_regs = FxHashMap::default();
1124         let mut used_output_regs = FxHashMap::default();
1125         for (idx, op) in operands.iter().enumerate() {
1126             let op_sp = asm.operands[idx].1;
1127             if let Some(reg) = op.reg() {
1128                 // Validate register classes against currently enabled target
1129                 // features. We check that at least one type is available for
1130                 // the current target.
1131                 let reg_class = reg.reg_class();
1132                 let mut required_features: Vec<&str> = vec![];
1133                 for &(_, feature) in reg_class.supported_types(asm_arch) {
1134                     if let Some(feature) = feature {
1135                         if self.sess.target_features.contains(&Symbol::intern(feature)) {
1136                             required_features.clear();
1137                             break;
1138                         } else {
1139                             required_features.push(feature);
1140                         }
1141                     } else {
1142                         required_features.clear();
1143                         break;
1144                     }
1145                 }
1146                 // We are sorting primitive strs here and can use unstable sort here
1147                 required_features.sort_unstable();
1148                 required_features.dedup();
1149                 match &required_features[..] {
1150                     [] => {}
1151                     [feature] => {
1152                         let msg = format!(
1153                             "register class `{}` requires the `{}` target feature",
1154                             reg_class.name(),
1155                             feature
1156                         );
1157                         sess.struct_span_err(op_sp, &msg).emit();
1158                     }
1159                     features => {
1160                         let msg = format!(
1161                             "register class `{}` requires at least one target feature: {}",
1162                             reg_class.name(),
1163                             features.join(", ")
1164                         );
1165                         sess.struct_span_err(op_sp, &msg).emit();
1166                     }
1167                 }
1168
1169                 // Check for conflicts between explicit register operands.
1170                 if let asm::InlineAsmRegOrRegClass::Reg(reg) = reg {
1171                     let (input, output) = match op {
1172                         hir::InlineAsmOperand::In { .. } => (true, false),
1173                         // Late output do not conflict with inputs, but normal outputs do
1174                         hir::InlineAsmOperand::Out { late, .. } => (!late, true),
1175                         hir::InlineAsmOperand::InOut { .. }
1176                         | hir::InlineAsmOperand::SplitInOut { .. } => (true, true),
1177                         hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::Sym { .. } => {
1178                             unreachable!()
1179                         }
1180                     };
1181
1182                     // Flag to output the error only once per operand
1183                     let mut skip = false;
1184                     reg.overlapping_regs(|r| {
1185                         let mut check = |used_regs: &mut FxHashMap<asm::InlineAsmReg, usize>,
1186                                          input| {
1187                             match used_regs.entry(r) {
1188                                 Entry::Occupied(o) => {
1189                                     if !skip {
1190                                         skip = true;
1191
1192                                         let idx2 = *o.get();
1193                                         let op2 = &operands[idx2];
1194                                         let op_sp2 = asm.operands[idx2].1;
1195                                         let reg2 = match op2.reg() {
1196                                             Some(asm::InlineAsmRegOrRegClass::Reg(r)) => r,
1197                                             _ => unreachable!(),
1198                                         };
1199
1200                                         let msg = format!(
1201                                             "register `{}` conflicts with register `{}`",
1202                                             reg.name(),
1203                                             reg2.name()
1204                                         );
1205                                         let mut err = sess.struct_span_err(op_sp, &msg);
1206                                         err.span_label(
1207                                             op_sp,
1208                                             &format!("register `{}`", reg.name()),
1209                                         );
1210                                         err.span_label(
1211                                             op_sp2,
1212                                             &format!("register `{}`", reg2.name()),
1213                                         );
1214
1215                                         match (op, op2) {
1216                                             (
1217                                                 hir::InlineAsmOperand::In { .. },
1218                                                 hir::InlineAsmOperand::Out { late, .. },
1219                                             )
1220                                             | (
1221                                                 hir::InlineAsmOperand::Out { late, .. },
1222                                                 hir::InlineAsmOperand::In { .. },
1223                                             ) => {
1224                                                 assert!(!*late);
1225                                                 let out_op_sp = if input { op_sp2 } else { op_sp };
1226                                                 let msg = "use `lateout` instead of \
1227                                                      `out` to avoid conflict";
1228                                                 err.span_help(out_op_sp, msg);
1229                                             }
1230                                             _ => {}
1231                                         }
1232
1233                                         err.emit();
1234                                     }
1235                                 }
1236                                 Entry::Vacant(v) => {
1237                                     v.insert(idx);
1238                                 }
1239                             }
1240                         };
1241                         if input {
1242                             check(&mut used_input_regs, true);
1243                         }
1244                         if output {
1245                             check(&mut used_output_regs, false);
1246                         }
1247                     });
1248                 }
1249             }
1250         }
1251
1252         let operands = self.arena.alloc_from_iter(operands);
1253         let template = self.arena.alloc_from_iter(asm.template.iter().cloned());
1254         let line_spans = self.arena.alloc_slice(&asm.line_spans[..]);
1255         let hir_asm = hir::InlineAsm { template, operands, options: asm.options, line_spans };
1256         hir::ExprKind::InlineAsm(self.arena.alloc(hir_asm))
1257     }
1258
1259     fn lower_expr_llvm_asm(&mut self, asm: &LlvmInlineAsm) -> hir::ExprKind<'hir> {
1260         let inner = hir::LlvmInlineAsmInner {
1261             inputs: asm.inputs.iter().map(|&(c, _)| c).collect(),
1262             outputs: asm
1263                 .outputs
1264                 .iter()
1265                 .map(|out| hir::LlvmInlineAsmOutput {
1266                     constraint: out.constraint,
1267                     is_rw: out.is_rw,
1268                     is_indirect: out.is_indirect,
1269                     span: out.expr.span,
1270                 })
1271                 .collect(),
1272             asm: asm.asm,
1273             asm_str_style: asm.asm_str_style,
1274             clobbers: asm.clobbers.clone(),
1275             volatile: asm.volatile,
1276             alignstack: asm.alignstack,
1277             dialect: asm.dialect,
1278         };
1279         let hir_asm = hir::LlvmInlineAsm {
1280             inner,
1281             inputs_exprs: self.arena.alloc_from_iter(
1282                 asm.inputs.iter().map(|&(_, ref input)| self.lower_expr_mut(input)),
1283             ),
1284             outputs_exprs: self
1285                 .arena
1286                 .alloc_from_iter(asm.outputs.iter().map(|out| self.lower_expr_mut(&out.expr))),
1287         };
1288         hir::ExprKind::LlvmInlineAsm(self.arena.alloc(hir_asm))
1289     }
1290
1291     fn lower_field(&mut self, f: &Field) -> hir::Field<'hir> {
1292         hir::Field {
1293             hir_id: self.next_id(),
1294             ident: f.ident,
1295             expr: self.lower_expr(&f.expr),
1296             span: f.span,
1297             is_shorthand: f.is_shorthand,
1298         }
1299     }
1300
1301     fn lower_expr_yield(&mut self, span: Span, opt_expr: Option<&Expr>) -> hir::ExprKind<'hir> {
1302         match self.generator_kind {
1303             Some(hir::GeneratorKind::Gen) => {}
1304             Some(hir::GeneratorKind::Async(_)) => {
1305                 struct_span_err!(
1306                     self.sess,
1307                     span,
1308                     E0727,
1309                     "`async` generators are not yet supported"
1310                 )
1311                 .emit();
1312             }
1313             None => self.generator_kind = Some(hir::GeneratorKind::Gen),
1314         }
1315
1316         let expr =
1317             opt_expr.as_ref().map(|x| self.lower_expr(x)).unwrap_or_else(|| self.expr_unit(span));
1318
1319         hir::ExprKind::Yield(expr, hir::YieldSource::Yield)
1320     }
1321
1322     /// Desugar `ExprForLoop` from: `[opt_ident]: for <pat> in <head> <body>` into:
1323     /// ```rust
1324     /// {
1325     ///     let result = match ::std::iter::IntoIterator::into_iter(<head>) {
1326     ///         mut iter => {
1327     ///             [opt_ident]: loop {
1328     ///                 let mut __next;
1329     ///                 match ::std::iter::Iterator::next(&mut iter) {
1330     ///                     ::std::option::Option::Some(val) => __next = val,
1331     ///                     ::std::option::Option::None => break
1332     ///                 };
1333     ///                 let <pat> = __next;
1334     ///                 StmtKind::Expr(<body>);
1335     ///             }
1336     ///         }
1337     ///     };
1338     ///     result
1339     /// }
1340     /// ```
1341     fn lower_expr_for(
1342         &mut self,
1343         e: &Expr,
1344         pat: &Pat,
1345         head: &Expr,
1346         body: &Block,
1347         opt_label: Option<Label>,
1348     ) -> hir::Expr<'hir> {
1349         let orig_head_span = head.span;
1350         // expand <head>
1351         let mut head = self.lower_expr_mut(head);
1352         let desugared_span = self.mark_span_with_reason(
1353             DesugaringKind::ForLoop(ForLoopLoc::Head),
1354             orig_head_span,
1355             None,
1356         );
1357         head.span = desugared_span;
1358
1359         let iter = Ident::with_dummy_span(sym::iter);
1360
1361         let next_ident = Ident::with_dummy_span(sym::__next);
1362         let (next_pat, next_pat_hid) = self.pat_ident_binding_mode(
1363             desugared_span,
1364             next_ident,
1365             hir::BindingAnnotation::Mutable,
1366         );
1367
1368         // `::std::option::Option::Some(val) => __next = val`
1369         let pat_arm = {
1370             let val_ident = Ident::with_dummy_span(sym::val);
1371             let (val_pat, val_pat_hid) = self.pat_ident(pat.span, val_ident);
1372             let val_expr = self.expr_ident(pat.span, val_ident, val_pat_hid);
1373             let next_expr = self.expr_ident(pat.span, next_ident, next_pat_hid);
1374             let assign = self.arena.alloc(self.expr(
1375                 pat.span,
1376                 hir::ExprKind::Assign(next_expr, val_expr, pat.span),
1377                 ThinVec::new(),
1378             ));
1379             let some_pat = self.pat_some(pat.span, val_pat);
1380             self.arm(some_pat, assign)
1381         };
1382
1383         // `::std::option::Option::None => break`
1384         let break_arm = {
1385             let break_expr =
1386                 self.with_loop_scope(e.id, |this| this.expr_break(e.span, ThinVec::new()));
1387             let pat = self.pat_none(e.span);
1388             self.arm(pat, break_expr)
1389         };
1390
1391         // `mut iter`
1392         let (iter_pat, iter_pat_nid) =
1393             self.pat_ident_binding_mode(desugared_span, iter, hir::BindingAnnotation::Mutable);
1394
1395         // `match ::std::iter::Iterator::next(&mut iter) { ... }`
1396         let match_expr = {
1397             let iter = self.expr_ident(desugared_span, iter, iter_pat_nid);
1398             let ref_mut_iter = self.expr_mut_addr_of(desugared_span, iter);
1399             let next_expr = self.expr_call_lang_item_fn(
1400                 desugared_span,
1401                 hir::LangItem::IteratorNext,
1402                 arena_vec![self; ref_mut_iter],
1403             );
1404             let arms = arena_vec![self; pat_arm, break_arm];
1405
1406             self.expr_match(desugared_span, next_expr, arms, hir::MatchSource::ForLoopDesugar)
1407         };
1408         let match_stmt = self.stmt_expr(desugared_span, match_expr);
1409
1410         let next_expr = self.expr_ident(desugared_span, next_ident, next_pat_hid);
1411
1412         // `let mut __next`
1413         let next_let = self.stmt_let_pat(
1414             ThinVec::new(),
1415             desugared_span,
1416             None,
1417             next_pat,
1418             hir::LocalSource::ForLoopDesugar,
1419         );
1420
1421         // `let <pat> = __next`
1422         let pat = self.lower_pat(pat);
1423         let pat_let = self.stmt_let_pat(
1424             ThinVec::new(),
1425             desugared_span,
1426             Some(next_expr),
1427             pat,
1428             hir::LocalSource::ForLoopDesugar,
1429         );
1430
1431         let body_block = self.with_loop_scope(e.id, |this| this.lower_block(body, false));
1432         let body_expr = self.expr_block(body_block, ThinVec::new());
1433         let body_stmt = self.stmt_expr(body.span, body_expr);
1434
1435         let loop_block = self.block_all(
1436             e.span,
1437             arena_vec![self; next_let, match_stmt, pat_let, body_stmt],
1438             None,
1439         );
1440
1441         // `[opt_ident]: loop { ... }`
1442         let kind = hir::ExprKind::Loop(loop_block, opt_label, hir::LoopSource::ForLoop);
1443         let loop_expr = self.arena.alloc(hir::Expr {
1444             hir_id: self.lower_node_id(e.id),
1445             kind,
1446             span: e.span,
1447             attrs: ThinVec::new(),
1448         });
1449
1450         // `mut iter => { ... }`
1451         let iter_arm = self.arm(iter_pat, loop_expr);
1452
1453         let into_iter_span = self.mark_span_with_reason(
1454             DesugaringKind::ForLoop(ForLoopLoc::IntoIter),
1455             orig_head_span,
1456             None,
1457         );
1458
1459         // `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
1460         let into_iter_expr = {
1461             self.expr_call_lang_item_fn(
1462                 into_iter_span,
1463                 hir::LangItem::IntoIterIntoIter,
1464                 arena_vec![self; head],
1465             )
1466         };
1467
1468         let match_expr = self.arena.alloc(self.expr_match(
1469             desugared_span,
1470             into_iter_expr,
1471             arena_vec![self; iter_arm],
1472             hir::MatchSource::ForLoopDesugar,
1473         ));
1474
1475         // This is effectively `{ let _result = ...; _result }`.
1476         // The construct was introduced in #21984 and is necessary to make sure that
1477         // temporaries in the `head` expression are dropped and do not leak to the
1478         // surrounding scope of the `match` since the `match` is not a terminating scope.
1479         //
1480         // Also, add the attributes to the outer returned expr node.
1481         self.expr_drop_temps_mut(desugared_span, match_expr, e.attrs.clone())
1482     }
1483
1484     /// Desugar `ExprKind::Try` from: `<expr>?` into:
1485     /// ```rust
1486     /// match Try::into_result(<expr>) {
1487     ///     Ok(val) => #[allow(unreachable_code)] val,
1488     ///     Err(err) => #[allow(unreachable_code)]
1489     ///                 // If there is an enclosing `try {...}`:
1490     ///                 break 'catch_target Try::from_error(From::from(err)),
1491     ///                 // Otherwise:
1492     ///                 return Try::from_error(From::from(err)),
1493     /// }
1494     /// ```
1495     fn lower_expr_try(&mut self, span: Span, sub_expr: &Expr) -> hir::ExprKind<'hir> {
1496         let unstable_span = self.mark_span_with_reason(
1497             DesugaringKind::QuestionMark,
1498             span,
1499             self.allow_try_trait.clone(),
1500         );
1501         let try_span = self.sess.source_map().end_point(span);
1502         let try_span = self.mark_span_with_reason(
1503             DesugaringKind::QuestionMark,
1504             try_span,
1505             self.allow_try_trait.clone(),
1506         );
1507
1508         // `Try::into_result(<expr>)`
1509         let scrutinee = {
1510             // expand <expr>
1511             let sub_expr = self.lower_expr_mut(sub_expr);
1512
1513             self.expr_call_lang_item_fn(
1514                 unstable_span,
1515                 hir::LangItem::TryIntoResult,
1516                 arena_vec![self; sub_expr],
1517             )
1518         };
1519
1520         // `#[allow(unreachable_code)]`
1521         let attr = {
1522             // `allow(unreachable_code)`
1523             let allow = {
1524                 let allow_ident = Ident::new(sym::allow, span);
1525                 let uc_ident = Ident::new(sym::unreachable_code, span);
1526                 let uc_nested = attr::mk_nested_word_item(uc_ident);
1527                 attr::mk_list_item(allow_ident, vec![uc_nested])
1528             };
1529             attr::mk_attr_outer(allow)
1530         };
1531         let attrs = vec![attr];
1532
1533         // `Ok(val) => #[allow(unreachable_code)] val,`
1534         let ok_arm = {
1535             let val_ident = Ident::with_dummy_span(sym::val);
1536             let (val_pat, val_pat_nid) = self.pat_ident(span, val_ident);
1537             let val_expr = self.arena.alloc(self.expr_ident_with_attrs(
1538                 span,
1539                 val_ident,
1540                 val_pat_nid,
1541                 ThinVec::from(attrs.clone()),
1542             ));
1543             let ok_pat = self.pat_ok(span, val_pat);
1544             self.arm(ok_pat, val_expr)
1545         };
1546
1547         // `Err(err) => #[allow(unreachable_code)]
1548         //              return Try::from_error(From::from(err)),`
1549         let err_arm = {
1550             let err_ident = Ident::with_dummy_span(sym::err);
1551             let (err_local, err_local_nid) = self.pat_ident(try_span, err_ident);
1552             let from_expr = {
1553                 let err_expr = self.expr_ident_mut(try_span, err_ident, err_local_nid);
1554                 self.expr_call_lang_item_fn(
1555                     try_span,
1556                     hir::LangItem::FromFrom,
1557                     arena_vec![self; err_expr],
1558                 )
1559             };
1560             let from_err_expr = self.wrap_in_try_constructor(
1561                 hir::LangItem::TryFromError,
1562                 unstable_span,
1563                 from_expr,
1564                 unstable_span,
1565             );
1566             let thin_attrs = ThinVec::from(attrs);
1567             let catch_scope = self.catch_scopes.last().copied();
1568             let ret_expr = if let Some(catch_node) = catch_scope {
1569                 let target_id = Ok(self.lower_node_id(catch_node));
1570                 self.arena.alloc(self.expr(
1571                     try_span,
1572                     hir::ExprKind::Break(
1573                         hir::Destination { label: None, target_id },
1574                         Some(from_err_expr),
1575                     ),
1576                     thin_attrs,
1577                 ))
1578             } else {
1579                 self.arena.alloc(self.expr(
1580                     try_span,
1581                     hir::ExprKind::Ret(Some(from_err_expr)),
1582                     thin_attrs,
1583                 ))
1584             };
1585
1586             let err_pat = self.pat_err(try_span, err_local);
1587             self.arm(err_pat, ret_expr)
1588         };
1589
1590         hir::ExprKind::Match(
1591             scrutinee,
1592             arena_vec![self; err_arm, ok_arm],
1593             hir::MatchSource::TryDesugar,
1594         )
1595     }
1596
1597     // =========================================================================
1598     // Helper methods for building HIR.
1599     // =========================================================================
1600
1601     /// Constructs a `true` or `false` literal expression.
1602     pub(super) fn expr_bool(&mut self, span: Span, val: bool) -> &'hir hir::Expr<'hir> {
1603         let lit = Spanned { span, node: LitKind::Bool(val) };
1604         self.arena.alloc(self.expr(span, hir::ExprKind::Lit(lit), ThinVec::new()))
1605     }
1606
1607     /// Wrap the given `expr` in a terminating scope using `hir::ExprKind::DropTemps`.
1608     ///
1609     /// In terms of drop order, it has the same effect as wrapping `expr` in
1610     /// `{ let _t = $expr; _t }` but should provide better compile-time performance.
1611     ///
1612     /// The drop order can be important in e.g. `if expr { .. }`.
1613     pub(super) fn expr_drop_temps(
1614         &mut self,
1615         span: Span,
1616         expr: &'hir hir::Expr<'hir>,
1617         attrs: AttrVec,
1618     ) -> &'hir hir::Expr<'hir> {
1619         self.arena.alloc(self.expr_drop_temps_mut(span, expr, attrs))
1620     }
1621
1622     pub(super) fn expr_drop_temps_mut(
1623         &mut self,
1624         span: Span,
1625         expr: &'hir hir::Expr<'hir>,
1626         attrs: AttrVec,
1627     ) -> hir::Expr<'hir> {
1628         self.expr(span, hir::ExprKind::DropTemps(expr), attrs)
1629     }
1630
1631     fn expr_match(
1632         &mut self,
1633         span: Span,
1634         arg: &'hir hir::Expr<'hir>,
1635         arms: &'hir [hir::Arm<'hir>],
1636         source: hir::MatchSource,
1637     ) -> hir::Expr<'hir> {
1638         self.expr(span, hir::ExprKind::Match(arg, arms, source), ThinVec::new())
1639     }
1640
1641     fn expr_break(&mut self, span: Span, attrs: AttrVec) -> &'hir hir::Expr<'hir> {
1642         let expr_break = hir::ExprKind::Break(self.lower_loop_destination(None), None);
1643         self.arena.alloc(self.expr(span, expr_break, attrs))
1644     }
1645
1646     fn expr_mut_addr_of(&mut self, span: Span, e: &'hir hir::Expr<'hir>) -> hir::Expr<'hir> {
1647         self.expr(
1648             span,
1649             hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, e),
1650             ThinVec::new(),
1651         )
1652     }
1653
1654     fn expr_unit(&mut self, sp: Span) -> &'hir hir::Expr<'hir> {
1655         self.arena.alloc(self.expr(sp, hir::ExprKind::Tup(&[]), ThinVec::new()))
1656     }
1657
1658     fn expr_call_mut(
1659         &mut self,
1660         span: Span,
1661         e: &'hir hir::Expr<'hir>,
1662         args: &'hir [hir::Expr<'hir>],
1663     ) -> hir::Expr<'hir> {
1664         self.expr(span, hir::ExprKind::Call(e, args), ThinVec::new())
1665     }
1666
1667     fn expr_call(
1668         &mut self,
1669         span: Span,
1670         e: &'hir hir::Expr<'hir>,
1671         args: &'hir [hir::Expr<'hir>],
1672     ) -> &'hir hir::Expr<'hir> {
1673         self.arena.alloc(self.expr_call_mut(span, e, args))
1674     }
1675
1676     fn expr_call_lang_item_fn_mut(
1677         &mut self,
1678         span: Span,
1679         lang_item: hir::LangItem,
1680         args: &'hir [hir::Expr<'hir>],
1681     ) -> hir::Expr<'hir> {
1682         let path = self.arena.alloc(self.expr_lang_item_path(span, lang_item, ThinVec::new()));
1683         self.expr_call_mut(span, path, args)
1684     }
1685
1686     fn expr_call_lang_item_fn(
1687         &mut self,
1688         span: Span,
1689         lang_item: hir::LangItem,
1690         args: &'hir [hir::Expr<'hir>],
1691     ) -> &'hir hir::Expr<'hir> {
1692         self.arena.alloc(self.expr_call_lang_item_fn_mut(span, lang_item, args))
1693     }
1694
1695     fn expr_lang_item_path(
1696         &mut self,
1697         span: Span,
1698         lang_item: hir::LangItem,
1699         attrs: AttrVec,
1700     ) -> hir::Expr<'hir> {
1701         self.expr(span, hir::ExprKind::Path(hir::QPath::LangItem(lang_item, span)), attrs)
1702     }
1703
1704     pub(super) fn expr_ident(
1705         &mut self,
1706         sp: Span,
1707         ident: Ident,
1708         binding: hir::HirId,
1709     ) -> &'hir hir::Expr<'hir> {
1710         self.arena.alloc(self.expr_ident_mut(sp, ident, binding))
1711     }
1712
1713     pub(super) fn expr_ident_mut(
1714         &mut self,
1715         sp: Span,
1716         ident: Ident,
1717         binding: hir::HirId,
1718     ) -> hir::Expr<'hir> {
1719         self.expr_ident_with_attrs(sp, ident, binding, ThinVec::new())
1720     }
1721
1722     fn expr_ident_with_attrs(
1723         &mut self,
1724         span: Span,
1725         ident: Ident,
1726         binding: hir::HirId,
1727         attrs: AttrVec,
1728     ) -> hir::Expr<'hir> {
1729         let expr_path = hir::ExprKind::Path(hir::QPath::Resolved(
1730             None,
1731             self.arena.alloc(hir::Path {
1732                 span,
1733                 res: Res::Local(binding),
1734                 segments: arena_vec![self; hir::PathSegment::from_ident(ident)],
1735             }),
1736         ));
1737
1738         self.expr(span, expr_path, attrs)
1739     }
1740
1741     fn expr_unsafe(&mut self, expr: &'hir hir::Expr<'hir>) -> hir::Expr<'hir> {
1742         let hir_id = self.next_id();
1743         let span = expr.span;
1744         self.expr(
1745             span,
1746             hir::ExprKind::Block(
1747                 self.arena.alloc(hir::Block {
1748                     stmts: &[],
1749                     expr: Some(expr),
1750                     hir_id,
1751                     rules: hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::CompilerGenerated),
1752                     span,
1753                     targeted_by_break: false,
1754                 }),
1755                 None,
1756             ),
1757             ThinVec::new(),
1758         )
1759     }
1760
1761     fn expr_block_empty(&mut self, span: Span) -> &'hir hir::Expr<'hir> {
1762         let blk = self.block_all(span, &[], None);
1763         let expr = self.expr_block(blk, ThinVec::new());
1764         self.arena.alloc(expr)
1765     }
1766
1767     pub(super) fn expr_block(
1768         &mut self,
1769         b: &'hir hir::Block<'hir>,
1770         attrs: AttrVec,
1771     ) -> hir::Expr<'hir> {
1772         self.expr(b.span, hir::ExprKind::Block(b, None), attrs)
1773     }
1774
1775     pub(super) fn expr(
1776         &mut self,
1777         span: Span,
1778         kind: hir::ExprKind<'hir>,
1779         attrs: AttrVec,
1780     ) -> hir::Expr<'hir> {
1781         hir::Expr { hir_id: self.next_id(), kind, span, attrs }
1782     }
1783
1784     fn field(&mut self, ident: Ident, expr: &'hir hir::Expr<'hir>, span: Span) -> hir::Field<'hir> {
1785         hir::Field { hir_id: self.next_id(), ident, span, expr, is_shorthand: false }
1786     }
1787
1788     fn arm(&mut self, pat: &'hir hir::Pat<'hir>, expr: &'hir hir::Expr<'hir>) -> hir::Arm<'hir> {
1789         hir::Arm {
1790             hir_id: self.next_id(),
1791             attrs: &[],
1792             pat,
1793             guard: None,
1794             span: expr.span,
1795             body: expr,
1796         }
1797     }
1798 }