]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir_build/build/mod.rs
Change MIR building to fill in the resume place
[rust.git] / src / librustc_mir_build / build / mod.rs
1 use crate::build;
2 use crate::build::scope::DropKind;
3 use crate::hair::cx::Cx;
4 use crate::hair::{BindingMode, LintLevel, PatKind};
5 use rustc::middle::lang_items;
6 use rustc::middle::region;
7 use rustc::mir::*;
8 use rustc::ty::subst::Subst;
9 use rustc::ty::{self, Ty, TyCtxt};
10 use rustc_attr::{self as attr, UnwindAttr};
11 use rustc_hir as hir;
12 use rustc_hir::def_id::DefId;
13 use rustc_hir::{GeneratorKind, HirIdMap, Node};
14 use rustc_index::vec::{Idx, IndexVec};
15 use rustc_span::symbol::kw;
16 use rustc_span::Span;
17 use rustc_target::spec::abi::Abi;
18 use rustc_target::spec::PanicStrategy;
19 use std::u32;
20
21 use super::lints;
22
23 crate fn mir_built(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::steal::Steal<BodyAndCache<'_>> {
24     tcx.alloc_steal_mir(mir_build(tcx, def_id))
25 }
26
27 /// Construct the MIR for a given `DefId`.
28 fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyAndCache<'_> {
29     let id = tcx.hir().as_local_hir_id(def_id).unwrap();
30
31     // Figure out what primary body this item has.
32     let (body_id, return_ty_span) = match tcx.hir().get(id) {
33         Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(_, decl, body_id, _, _), .. }) => {
34             (*body_id, decl.output.span())
35         }
36         Node::Item(hir::Item {
37             kind: hir::ItemKind::Fn(hir::FnSig { decl, .. }, _, body_id),
38             ..
39         })
40         | Node::ImplItem(hir::ImplItem {
41             kind: hir::ImplItemKind::Method(hir::FnSig { decl, .. }, body_id),
42             ..
43         })
44         | Node::TraitItem(hir::TraitItem {
45             kind:
46                 hir::TraitItemKind::Method(hir::FnSig { decl, .. }, hir::TraitMethod::Provided(body_id)),
47             ..
48         }) => (*body_id, decl.output.span()),
49         Node::Item(hir::Item { kind: hir::ItemKind::Static(ty, _, body_id), .. })
50         | Node::Item(hir::Item { kind: hir::ItemKind::Const(ty, body_id), .. })
51         | Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(ty, body_id), .. })
52         | Node::TraitItem(hir::TraitItem {
53             kind: hir::TraitItemKind::Const(ty, Some(body_id)),
54             ..
55         }) => (*body_id, ty.span),
56         Node::AnonConst(hir::AnonConst { body, hir_id, .. }) => (*body, tcx.hir().span(*hir_id)),
57
58         _ => span_bug!(tcx.hir().span(id), "can't build MIR for {:?}", def_id),
59     };
60
61     tcx.infer_ctxt().enter(|infcx| {
62         let cx = Cx::new(&infcx, id);
63         let body = if cx.tables().tainted_by_errors {
64             build::construct_error(cx, body_id)
65         } else if cx.body_owner_kind.is_fn_or_closure() {
66             // fetch the fully liberated fn signature (that is, all bound
67             // types/lifetimes replaced)
68             let fn_sig = cx.tables().liberated_fn_sigs()[id];
69             let fn_def_id = tcx.hir().local_def_id(id);
70
71             let safety = match fn_sig.unsafety {
72                 hir::Unsafety::Normal => Safety::Safe,
73                 hir::Unsafety::Unsafe => Safety::FnUnsafe,
74             };
75
76             let body = tcx.hir().body(body_id);
77             let ty = tcx.type_of(fn_def_id);
78             let mut abi = fn_sig.abi;
79             let implicit_argument = match ty.kind {
80                 ty::Closure(..) => {
81                     // HACK(eddyb) Avoid having RustCall on closures,
82                     // as it adds unnecessary (and wrong) auto-tupling.
83                     abi = Abi::Rust;
84                     vec![ArgInfo(liberated_closure_env_ty(tcx, id, body_id), None, None, None)]
85                 }
86                 ty::Generator(def_id, substs, _) => {
87                     let gen_ty = tcx.body_tables(body_id).node_type(id);
88                     let resume_ty = substs.as_generator().resume_ty(def_id, tcx);
89
90                     // The resume argument may be missing, in that case we need to provide it here.
91                     if body.params.is_empty() {
92                         vec![
93                             ArgInfo(gen_ty, None, None, None),
94                             ArgInfo(resume_ty, None, None, None),
95                         ]
96                     } else {
97                         vec![ArgInfo(gen_ty, None, None, None)]
98                     }
99                 }
100                 _ => vec![],
101             };
102
103             let explicit_arguments = body.params.iter().enumerate().map(|(index, arg)| {
104                 let owner_id = tcx.hir().body_owner(body_id);
105                 let opt_ty_info;
106                 let self_arg;
107                 if let Some(ref fn_decl) = tcx.hir().fn_decl_by_hir_id(owner_id) {
108                     opt_ty_info = fn_decl.inputs.get(index).map(|ty| ty.span);
109                     self_arg = if index == 0 && fn_decl.implicit_self.has_implicit_self() {
110                         match fn_decl.implicit_self {
111                             hir::ImplicitSelfKind::Imm => Some(ImplicitSelfKind::Imm),
112                             hir::ImplicitSelfKind::Mut => Some(ImplicitSelfKind::Mut),
113                             hir::ImplicitSelfKind::ImmRef => Some(ImplicitSelfKind::ImmRef),
114                             hir::ImplicitSelfKind::MutRef => Some(ImplicitSelfKind::MutRef),
115                             _ => None,
116                         }
117                     } else {
118                         None
119                     };
120                 } else {
121                     opt_ty_info = None;
122                     self_arg = None;
123                 }
124
125                 // C-variadic fns also have a `VaList` input that's not listed in `fn_sig`
126                 // (as it's created inside the body itself, not passed in from outside).
127                 let ty = if fn_sig.c_variadic && index == fn_sig.inputs().len() {
128                     let va_list_did =
129                         tcx.require_lang_item(lang_items::VaListTypeLangItem, Some(arg.span));
130                     let region = tcx.mk_region(ty::ReScope(region::Scope {
131                         id: body.value.hir_id.local_id,
132                         data: region::ScopeData::CallSite,
133                     }));
134
135                     tcx.type_of(va_list_did).subst(tcx, &[region.into()])
136                 } else {
137                     fn_sig.inputs()[index]
138                 };
139
140                 ArgInfo(ty, opt_ty_info, Some(&arg), self_arg)
141             });
142
143             let arguments = implicit_argument.into_iter().chain(explicit_arguments);
144
145             let (yield_ty, return_ty) = if body.generator_kind.is_some() {
146                 let gen_sig = match ty.kind {
147                     ty::Generator(gen_def_id, gen_substs, ..) => {
148                         gen_substs.as_generator().sig(gen_def_id, tcx)
149                     }
150                     _ => span_bug!(tcx.hir().span(id), "generator w/o generator type: {:?}", ty),
151                 };
152                 (Some(gen_sig.yield_ty), gen_sig.return_ty)
153             } else {
154                 (None, fn_sig.output())
155             };
156
157             let mut mir = build::construct_fn(
158                 cx,
159                 id,
160                 arguments,
161                 safety,
162                 abi,
163                 return_ty,
164                 return_ty_span,
165                 body,
166             );
167             mir.yield_ty = yield_ty;
168             mir
169         } else {
170             // Get the revealed type of this const. This is *not* the adjusted
171             // type of its body, which may be a subtype of this type. For
172             // example:
173             //
174             // fn foo(_: &()) {}
175             // static X: fn(&'static ()) = foo;
176             //
177             // The adjusted type of the body of X is `for<'a> fn(&'a ())` which
178             // is not the same as the type of X. We need the type of the return
179             // place to be the type of the constant because NLL typeck will
180             // equate them.
181
182             let return_ty = cx.tables().node_type(id);
183
184             build::construct_const(cx, body_id, return_ty, return_ty_span)
185         };
186
187         lints::check(tcx, &body, def_id);
188
189         let mut body = BodyAndCache::new(body);
190         body.ensure_predecessors();
191         body
192     })
193 }
194
195 ///////////////////////////////////////////////////////////////////////////
196 // BuildMir -- walks a crate, looking for fn items and methods to build MIR from
197
198 fn liberated_closure_env_ty(
199     tcx: TyCtxt<'_>,
200     closure_expr_id: hir::HirId,
201     body_id: hir::BodyId,
202 ) -> Ty<'_> {
203     let closure_ty = tcx.body_tables(body_id).node_type(closure_expr_id);
204
205     let (closure_def_id, closure_substs) = match closure_ty.kind {
206         ty::Closure(closure_def_id, closure_substs) => (closure_def_id, closure_substs),
207         _ => bug!("closure expr does not have closure type: {:?}", closure_ty),
208     };
209
210     let closure_env_ty = tcx.closure_env_ty(closure_def_id, closure_substs).unwrap();
211     tcx.liberate_late_bound_regions(closure_def_id, &closure_env_ty)
212 }
213
214 #[derive(Debug, PartialEq, Eq)]
215 enum BlockFrame {
216     /// Evaluation is currently within a statement.
217     ///
218     /// Examples include:
219     /// 1. `EXPR;`
220     /// 2. `let _ = EXPR;`
221     /// 3. `let x = EXPR;`
222     Statement {
223         /// If true, then statement discards result from evaluating
224         /// the expression (such as examples 1 and 2 above).
225         ignores_expr_result: bool,
226     },
227
228     /// Evaluation is currently within the tail expression of a block.
229     ///
230     /// Example: `{ STMT_1; STMT_2; EXPR }`
231     TailExpr {
232         /// If true, then the surrounding context of the block ignores
233         /// the result of evaluating the block's tail expression.
234         ///
235         /// Example: `let _ = { STMT_1; EXPR };`
236         tail_result_is_ignored: bool,
237     },
238
239     /// Generic mark meaning that the block occurred as a subexpression
240     /// where the result might be used.
241     ///
242     /// Examples: `foo(EXPR)`, `match EXPR { ... }`
243     SubExpr,
244 }
245
246 impl BlockFrame {
247     fn is_tail_expr(&self) -> bool {
248         match *self {
249             BlockFrame::TailExpr { .. } => true,
250
251             BlockFrame::Statement { .. } | BlockFrame::SubExpr => false,
252         }
253     }
254     fn is_statement(&self) -> bool {
255         match *self {
256             BlockFrame::Statement { .. } => true,
257
258             BlockFrame::TailExpr { .. } | BlockFrame::SubExpr => false,
259         }
260     }
261 }
262
263 #[derive(Debug)]
264 struct BlockContext(Vec<BlockFrame>);
265
266 struct Builder<'a, 'tcx> {
267     hir: Cx<'a, 'tcx>,
268     cfg: CFG<'tcx>,
269
270     fn_span: Span,
271     arg_count: usize,
272     generator_kind: Option<GeneratorKind>,
273
274     /// The current set of scopes, updated as we traverse;
275     /// see the `scope` module for more details.
276     scopes: scope::Scopes<'tcx>,
277
278     /// The block-context: each time we build the code within an hair::Block,
279     /// we push a frame here tracking whether we are building a statement or
280     /// if we are pushing the tail expression of the block. This is used to
281     /// embed information in generated temps about whether they were created
282     /// for a block tail expression or not.
283     ///
284     /// It would be great if we could fold this into `self.scopes`
285     /// somehow, but right now I think that is very tightly tied to
286     /// the code generation in ways that we cannot (or should not)
287     /// start just throwing new entries onto that vector in order to
288     /// distinguish the context of EXPR1 from the context of EXPR2 in
289     /// `{ STMTS; EXPR1 } + EXPR2`.
290     block_context: BlockContext,
291
292     /// The current unsafe block in scope, even if it is hidden by
293     /// a `PushUnsafeBlock`.
294     unpushed_unsafe: Safety,
295
296     /// The number of `push_unsafe_block` levels in scope.
297     push_unsafe_count: usize,
298
299     /// The vector of all scopes that we have created thus far;
300     /// we track this for debuginfo later.
301     source_scopes: IndexVec<SourceScope, SourceScopeData>,
302     source_scope: SourceScope,
303
304     /// The guard-context: each time we build the guard expression for
305     /// a match arm, we push onto this stack, and then pop when we
306     /// finish building it.
307     guard_context: Vec<GuardFrame>,
308
309     /// Maps `HirId`s of variable bindings to the `Local`s created for them.
310     /// (A match binding can have two locals; the 2nd is for the arm's guard.)
311     var_indices: HirIdMap<LocalsForNode>,
312     local_decls: IndexVec<Local, LocalDecl<'tcx>>,
313     canonical_user_type_annotations: ty::CanonicalUserTypeAnnotations<'tcx>,
314     upvar_mutbls: Vec<Mutability>,
315     unit_temp: Option<Place<'tcx>>,
316
317     var_debug_info: Vec<VarDebugInfo<'tcx>>,
318
319     /// Cached block with the `RESUME` terminator; this is created
320     /// when first set of cleanups are built.
321     cached_resume_block: Option<BasicBlock>,
322     /// Cached block with the `RETURN` terminator.
323     cached_return_block: Option<BasicBlock>,
324     /// Cached block with the `UNREACHABLE` terminator.
325     cached_unreachable_block: Option<BasicBlock>,
326 }
327
328 impl<'a, 'tcx> Builder<'a, 'tcx> {
329     fn is_bound_var_in_guard(&self, id: hir::HirId) -> bool {
330         self.guard_context.iter().any(|frame| frame.locals.iter().any(|local| local.id == id))
331     }
332
333     fn var_local_id(&self, id: hir::HirId, for_guard: ForGuard) -> Local {
334         self.var_indices[&id].local_id(for_guard)
335     }
336 }
337
338 impl BlockContext {
339     fn new() -> Self {
340         BlockContext(vec![])
341     }
342     fn push(&mut self, bf: BlockFrame) {
343         self.0.push(bf);
344     }
345     fn pop(&mut self) -> Option<BlockFrame> {
346         self.0.pop()
347     }
348
349     /// Traverses the frames on the `BlockContext`, searching for either
350     /// the first block-tail expression frame with no intervening
351     /// statement frame.
352     ///
353     /// Notably, this skips over `SubExpr` frames; this method is
354     /// meant to be used in the context of understanding the
355     /// relationship of a temp (created within some complicated
356     /// expression) with its containing expression, and whether the
357     /// value of that *containing expression* (not the temp!) is
358     /// ignored.
359     fn currently_in_block_tail(&self) -> Option<BlockTailInfo> {
360         for bf in self.0.iter().rev() {
361             match bf {
362                 BlockFrame::SubExpr => continue,
363                 BlockFrame::Statement { .. } => break,
364                 &BlockFrame::TailExpr { tail_result_is_ignored } => {
365                     return Some(BlockTailInfo { tail_result_is_ignored });
366                 }
367             }
368         }
369
370         return None;
371     }
372
373     /// Looks at the topmost frame on the BlockContext and reports
374     /// whether its one that would discard a block tail result.
375     ///
376     /// Unlike `currently_within_ignored_tail_expression`, this does
377     /// *not* skip over `SubExpr` frames: here, we want to know
378     /// whether the block result itself is discarded.
379     fn currently_ignores_tail_results(&self) -> bool {
380         match self.0.last() {
381             // no context: conservatively assume result is read
382             None => false,
383
384             // sub-expression: block result feeds into some computation
385             Some(BlockFrame::SubExpr) => false,
386
387             // otherwise: use accumulated is_ignored state.
388             Some(BlockFrame::TailExpr { tail_result_is_ignored: ignored })
389             | Some(BlockFrame::Statement { ignores_expr_result: ignored }) => *ignored,
390         }
391     }
392 }
393
394 #[derive(Debug)]
395 enum LocalsForNode {
396     /// In the usual case, a `HirId` for an identifier maps to at most
397     /// one `Local` declaration.
398     One(Local),
399
400     /// The exceptional case is identifiers in a match arm's pattern
401     /// that are referenced in a guard of that match arm. For these,
402     /// we have `2` Locals.
403     ///
404     /// * `for_arm_body` is the Local used in the arm body (which is
405     ///   just like the `One` case above),
406     ///
407     /// * `ref_for_guard` is the Local used in the arm's guard (which
408     ///   is a reference to a temp that is an alias of
409     ///   `for_arm_body`).
410     ForGuard { ref_for_guard: Local, for_arm_body: Local },
411 }
412
413 #[derive(Debug)]
414 struct GuardFrameLocal {
415     id: hir::HirId,
416 }
417
418 impl GuardFrameLocal {
419     fn new(id: hir::HirId, _binding_mode: BindingMode) -> Self {
420         GuardFrameLocal { id: id }
421     }
422 }
423
424 #[derive(Debug)]
425 struct GuardFrame {
426     /// These are the id's of names that are bound by patterns of the
427     /// arm of *this* guard.
428     ///
429     /// (Frames higher up the stack will have the id's bound in arms
430     /// further out, such as in a case like:
431     ///
432     /// match E1 {
433     ///      P1(id1) if (... (match E2 { P2(id2) if ... => B2 })) => B1,
434     /// }
435     ///
436     /// here, when building for FIXME.
437     locals: Vec<GuardFrameLocal>,
438 }
439
440 /// `ForGuard` indicates whether we are talking about:
441 ///   1. The variable for use outside of guard expressions, or
442 ///   2. The temp that holds reference to (1.), which is actually what the
443 ///      guard expressions see.
444 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
445 enum ForGuard {
446     RefWithinGuard,
447     OutsideGuard,
448 }
449
450 impl LocalsForNode {
451     fn local_id(&self, for_guard: ForGuard) -> Local {
452         match (self, for_guard) {
453             (&LocalsForNode::One(local_id), ForGuard::OutsideGuard)
454             | (
455                 &LocalsForNode::ForGuard { ref_for_guard: local_id, .. },
456                 ForGuard::RefWithinGuard,
457             )
458             | (&LocalsForNode::ForGuard { for_arm_body: local_id, .. }, ForGuard::OutsideGuard) => {
459                 local_id
460             }
461
462             (&LocalsForNode::One(_), ForGuard::RefWithinGuard) => {
463                 bug!("anything with one local should never be within a guard.")
464             }
465         }
466     }
467 }
468
469 struct CFG<'tcx> {
470     basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
471 }
472
473 rustc_index::newtype_index! {
474     struct ScopeId { .. }
475 }
476
477 ///////////////////////////////////////////////////////////////////////////
478 /// The `BlockAnd` "monad" packages up the new basic block along with a
479 /// produced value (sometimes just unit, of course). The `unpack!`
480 /// macro (and methods below) makes working with `BlockAnd` much more
481 /// convenient.
482
483 #[must_use = "if you don't use one of these results, you're leaving a dangling edge"]
484 struct BlockAnd<T>(BasicBlock, T);
485
486 trait BlockAndExtension {
487     fn and<T>(self, v: T) -> BlockAnd<T>;
488     fn unit(self) -> BlockAnd<()>;
489 }
490
491 impl BlockAndExtension for BasicBlock {
492     fn and<T>(self, v: T) -> BlockAnd<T> {
493         BlockAnd(self, v)
494     }
495
496     fn unit(self) -> BlockAnd<()> {
497         BlockAnd(self, ())
498     }
499 }
500
501 /// Update a block pointer and return the value.
502 /// Use it like `let x = unpack!(block = self.foo(block, foo))`.
503 macro_rules! unpack {
504     ($x:ident = $c:expr) => {{
505         let BlockAnd(b, v) = $c;
506         $x = b;
507         v
508     }};
509
510     ($c:expr) => {{
511         let BlockAnd(b, ()) = $c;
512         b
513     }};
514 }
515
516 fn should_abort_on_panic(tcx: TyCtxt<'_>, fn_def_id: DefId, _abi: Abi) -> bool {
517     // Validate `#[unwind]` syntax regardless of platform-specific panic strategy.
518     let attrs = &tcx.get_attrs(fn_def_id);
519     let unwind_attr = attr::find_unwind_attr(Some(tcx.sess.diagnostic()), attrs);
520
521     // We never unwind, so it's not relevant to stop an unwind.
522     if tcx.sess.panic_strategy() != PanicStrategy::Unwind {
523         return false;
524     }
525
526     // We cannot add landing pads, so don't add one.
527     if tcx.sess.no_landing_pads() {
528         return false;
529     }
530
531     // This is a special case: some functions have a C abi but are meant to
532     // unwind anyway. Don't stop them.
533     match unwind_attr {
534         None => false, // FIXME(#58794); should be `!(abi == Abi::Rust || abi == Abi::RustCall)`
535         Some(UnwindAttr::Allowed) => false,
536         Some(UnwindAttr::Aborts) => true,
537     }
538 }
539
540 ///////////////////////////////////////////////////////////////////////////
541 /// the main entry point for building MIR for a function
542
543 struct ArgInfo<'tcx>(
544     Ty<'tcx>,
545     Option<Span>,
546     Option<&'tcx hir::Param<'tcx>>,
547     Option<ImplicitSelfKind>,
548 );
549
550 fn construct_fn<'a, 'tcx, A>(
551     hir: Cx<'a, 'tcx>,
552     fn_id: hir::HirId,
553     arguments: A,
554     safety: Safety,
555     abi: Abi,
556     return_ty: Ty<'tcx>,
557     return_ty_span: Span,
558     body: &'tcx hir::Body<'tcx>,
559 ) -> Body<'tcx>
560 where
561     A: Iterator<Item = ArgInfo<'tcx>>,
562 {
563     let arguments: Vec<_> = arguments.collect();
564
565     let tcx = hir.tcx();
566     let tcx_hir = tcx.hir();
567     let span = tcx_hir.span(fn_id);
568
569     let fn_def_id = tcx_hir.local_def_id(fn_id);
570
571     let mut builder = Builder::new(
572         hir,
573         span,
574         arguments.len(),
575         safety,
576         return_ty,
577         return_ty_span,
578         body.generator_kind,
579     );
580
581     let call_site_scope =
582         region::Scope { id: body.value.hir_id.local_id, data: region::ScopeData::CallSite };
583     let arg_scope =
584         region::Scope { id: body.value.hir_id.local_id, data: region::ScopeData::Arguments };
585     let mut block = START_BLOCK;
586     let source_info = builder.source_info(span);
587     let call_site_s = (call_site_scope, source_info);
588     unpack!(
589         block = builder.in_scope(call_site_s, LintLevel::Inherited, |builder| {
590             if should_abort_on_panic(tcx, fn_def_id, abi) {
591                 builder.schedule_abort();
592             }
593
594             let arg_scope_s = (arg_scope, source_info);
595             // `return_block` is called when we evaluate a `return` expression, so
596             // we just use `START_BLOCK` here.
597             unpack!(
598                 block = builder.in_breakable_scope(
599                     None,
600                     START_BLOCK,
601                     Place::return_place(),
602                     |builder| {
603                         builder.in_scope(arg_scope_s, LintLevel::Inherited, |builder| {
604                             builder.args_and_body(
605                                 block,
606                                 fn_def_id,
607                                 &arguments,
608                                 arg_scope,
609                                 &body.value,
610                             )
611                         })
612                     },
613                 )
614             );
615             // Attribute epilogue to function's closing brace
616             let fn_end = span.shrink_to_hi();
617             let source_info = builder.source_info(fn_end);
618             let return_block = builder.return_block();
619             builder.cfg.goto(block, source_info, return_block);
620             builder.cfg.terminate(return_block, source_info, TerminatorKind::Return);
621             // Attribute any unreachable codepaths to the function's closing brace
622             if let Some(unreachable_block) = builder.cached_unreachable_block {
623                 builder.cfg.terminate(unreachable_block, source_info, TerminatorKind::Unreachable);
624             }
625             return_block.unit()
626         })
627     );
628     assert_eq!(block, builder.return_block());
629
630     let mut spread_arg = None;
631     if abi == Abi::RustCall {
632         // RustCall pseudo-ABI untuples the last argument.
633         spread_arg = Some(Local::new(arguments.len()));
634     }
635     debug!("fn_id {:?} has attrs {:?}", fn_def_id, tcx.get_attrs(fn_def_id));
636
637     let mut body = builder.finish();
638     body.spread_arg = spread_arg;
639     body
640 }
641
642 fn construct_const<'a, 'tcx>(
643     hir: Cx<'a, 'tcx>,
644     body_id: hir::BodyId,
645     const_ty: Ty<'tcx>,
646     const_ty_span: Span,
647 ) -> Body<'tcx> {
648     let tcx = hir.tcx();
649     let owner_id = tcx.hir().body_owner(body_id);
650     let span = tcx.hir().span(owner_id);
651     let mut builder = Builder::new(hir, span, 0, Safety::Safe, const_ty, const_ty_span, None);
652
653     let mut block = START_BLOCK;
654     let ast_expr = &tcx.hir().body(body_id).value;
655     let expr = builder.hir.mirror(ast_expr);
656     unpack!(block = builder.into_expr(&Place::return_place(), block, expr));
657
658     let source_info = builder.source_info(span);
659     builder.cfg.terminate(block, source_info, TerminatorKind::Return);
660
661     // Constants can't `return` so a return block should not be created.
662     assert_eq!(builder.cached_return_block, None);
663
664     // Constants may be match expressions in which case an unreachable block may
665     // be created, so terminate it properly.
666     if let Some(unreachable_block) = builder.cached_unreachable_block {
667         builder.cfg.terminate(unreachable_block, source_info, TerminatorKind::Unreachable);
668     }
669
670     builder.finish()
671 }
672
673 fn construct_error<'a, 'tcx>(hir: Cx<'a, 'tcx>, body_id: hir::BodyId) -> Body<'tcx> {
674     let owner_id = hir.tcx().hir().body_owner(body_id);
675     let span = hir.tcx().hir().span(owner_id);
676     let ty = hir.tcx().types.err;
677     let mut builder = Builder::new(hir, span, 0, Safety::Safe, ty, span, None);
678     let source_info = builder.source_info(span);
679     builder.cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable);
680     builder.finish()
681 }
682
683 impl<'a, 'tcx> Builder<'a, 'tcx> {
684     fn new(
685         hir: Cx<'a, 'tcx>,
686         span: Span,
687         arg_count: usize,
688         safety: Safety,
689         return_ty: Ty<'tcx>,
690         return_span: Span,
691         generator_kind: Option<GeneratorKind>,
692     ) -> Builder<'a, 'tcx> {
693         let lint_level = LintLevel::Explicit(hir.root_lint_level);
694         let mut builder = Builder {
695             hir,
696             cfg: CFG { basic_blocks: IndexVec::new() },
697             fn_span: span,
698             arg_count,
699             generator_kind,
700             scopes: Default::default(),
701             block_context: BlockContext::new(),
702             source_scopes: IndexVec::new(),
703             source_scope: OUTERMOST_SOURCE_SCOPE,
704             guard_context: vec![],
705             push_unsafe_count: 0,
706             unpushed_unsafe: safety,
707             local_decls: IndexVec::from_elem_n(
708                 LocalDecl::new_return_place(return_ty, return_span),
709                 1,
710             ),
711             canonical_user_type_annotations: IndexVec::new(),
712             upvar_mutbls: vec![],
713             var_indices: Default::default(),
714             unit_temp: None,
715             var_debug_info: vec![],
716             cached_resume_block: None,
717             cached_return_block: None,
718             cached_unreachable_block: None,
719         };
720
721         assert_eq!(builder.cfg.start_new_block(), START_BLOCK);
722         assert_eq!(
723             builder.new_source_scope(span, lint_level, Some(safety)),
724             OUTERMOST_SOURCE_SCOPE
725         );
726         builder.source_scopes[OUTERMOST_SOURCE_SCOPE].parent_scope = None;
727
728         builder
729     }
730
731     fn finish(self) -> Body<'tcx> {
732         for (index, block) in self.cfg.basic_blocks.iter().enumerate() {
733             if block.terminator.is_none() {
734                 span_bug!(self.fn_span, "no terminator on block {:?}", index);
735             }
736         }
737
738         Body::new(
739             self.cfg.basic_blocks,
740             self.source_scopes,
741             self.local_decls,
742             self.canonical_user_type_annotations,
743             self.arg_count,
744             self.var_debug_info,
745             self.fn_span,
746             self.hir.control_flow_destroyed(),
747             self.generator_kind,
748         )
749     }
750
751     fn args_and_body(
752         &mut self,
753         mut block: BasicBlock,
754         fn_def_id: DefId,
755         arguments: &[ArgInfo<'tcx>],
756         argument_scope: region::Scope,
757         ast_body: &'tcx hir::Expr<'tcx>,
758     ) -> BlockAnd<()> {
759         // Allocate locals for the function arguments
760         for &ArgInfo(ty, _, arg_opt, _) in arguments.iter() {
761             let source_info = SourceInfo {
762                 scope: OUTERMOST_SOURCE_SCOPE,
763                 span: arg_opt.map_or(self.fn_span, |arg| arg.pat.span),
764             };
765             let arg_local = self.local_decls.push(LocalDecl {
766                 mutability: Mutability::Mut,
767                 ty,
768                 user_ty: UserTypeProjections::none(),
769                 source_info,
770                 internal: false,
771                 local_info: LocalInfo::Other,
772                 is_block_tail: None,
773             });
774
775             // If this is a simple binding pattern, give debuginfo a nice name.
776             if let Some(arg) = arg_opt {
777                 if let Some(ident) = arg.pat.simple_ident() {
778                     self.var_debug_info.push(VarDebugInfo {
779                         name: ident.name,
780                         source_info,
781                         place: arg_local.into(),
782                     });
783                 }
784             }
785         }
786
787         let tcx = self.hir.tcx();
788         let tcx_hir = tcx.hir();
789         let hir_tables = self.hir.tables();
790
791         // In analyze_closure() in upvar.rs we gathered a list of upvars used by a
792         // closure and we stored in a map called upvar_list in TypeckTables indexed
793         // with the closure's DefId. Here, we run through that vec of UpvarIds for
794         // the given closure and use the necessary information to create upvar
795         // debuginfo and to fill `self.upvar_mutbls`.
796         if let Some(upvars) = hir_tables.upvar_list.get(&fn_def_id) {
797             let closure_env_arg = Local::new(1);
798             let mut closure_env_projs = vec![];
799             let mut closure_ty = self.local_decls[closure_env_arg].ty;
800             if let ty::Ref(_, ty, _) = closure_ty.kind {
801                 closure_env_projs.push(ProjectionElem::Deref);
802                 closure_ty = ty;
803             }
804             let (def_id, upvar_substs) = match closure_ty.kind {
805                 ty::Closure(def_id, substs) => (def_id, ty::UpvarSubsts::Closure(substs)),
806                 ty::Generator(def_id, substs, _) => (def_id, ty::UpvarSubsts::Generator(substs)),
807                 _ => span_bug!(self.fn_span, "upvars with non-closure env ty {:?}", closure_ty),
808             };
809             let upvar_tys = upvar_substs.upvar_tys(def_id, tcx);
810             let upvars_with_tys = upvars.iter().zip(upvar_tys);
811             self.upvar_mutbls = upvars_with_tys
812                 .enumerate()
813                 .map(|(i, ((&var_id, &upvar_id), ty))| {
814                     let capture = hir_tables.upvar_capture(upvar_id);
815
816                     let mut mutability = Mutability::Not;
817                     let mut name = kw::Invalid;
818                     if let Some(Node::Binding(pat)) = tcx_hir.find(var_id) {
819                         if let hir::PatKind::Binding(_, _, ident, _) = pat.kind {
820                             name = ident.name;
821                             match hir_tables.extract_binding_mode(tcx.sess, pat.hir_id, pat.span) {
822                                 Some(ty::BindByValue(hir::Mutability::Mut)) => {
823                                     mutability = Mutability::Mut;
824                                 }
825                                 Some(_) => mutability = Mutability::Not,
826                                 _ => {}
827                             }
828                         }
829                     }
830
831                     let mut projs = closure_env_projs.clone();
832                     projs.push(ProjectionElem::Field(Field::new(i), ty));
833                     match capture {
834                         ty::UpvarCapture::ByValue => {}
835                         ty::UpvarCapture::ByRef(..) => {
836                             projs.push(ProjectionElem::Deref);
837                         }
838                     };
839
840                     self.var_debug_info.push(VarDebugInfo {
841                         name,
842                         source_info: SourceInfo {
843                             scope: OUTERMOST_SOURCE_SCOPE,
844                             span: tcx_hir.span(var_id),
845                         },
846                         place: Place {
847                             local: closure_env_arg.into(),
848                             projection: tcx.intern_place_elems(&projs),
849                         },
850                     });
851
852                     mutability
853                 })
854                 .collect();
855         }
856
857         let mut scope = None;
858         // Bind the argument patterns
859         for (index, arg_info) in arguments.iter().enumerate() {
860             // Function arguments always get the first Local indices after the return place
861             let local = Local::new(index + 1);
862             let place = Place::from(local);
863             let &ArgInfo(_, opt_ty_info, arg_opt, ref self_binding) = arg_info;
864
865             // Make sure we drop (parts of) the argument even when not matched on.
866             self.schedule_drop(
867                 arg_opt.as_ref().map_or(ast_body.span, |arg| arg.pat.span),
868                 argument_scope,
869                 local,
870                 DropKind::Value,
871             );
872
873             if let Some(arg) = arg_opt {
874                 let pattern = self.hir.pattern_from_hir(&arg.pat);
875                 let original_source_scope = self.source_scope;
876                 let span = pattern.span;
877                 self.set_correct_source_scope_for_arg(arg.hir_id, original_source_scope, span);
878                 match *pattern.kind {
879                     // Don't introduce extra copies for simple bindings
880                     PatKind::Binding {
881                         mutability,
882                         var,
883                         mode: BindingMode::ByValue,
884                         subpattern: None,
885                         ..
886                     } => {
887                         self.local_decls[local].mutability = mutability;
888                         self.local_decls[local].source_info.scope = self.source_scope;
889                         self.local_decls[local].local_info = if let Some(kind) = self_binding {
890                             LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(*kind)))
891                         } else {
892                             let binding_mode = ty::BindingMode::BindByValue(mutability.into());
893                             LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
894                                 VarBindingForm {
895                                     binding_mode,
896                                     opt_ty_info,
897                                     opt_match_place: Some((Some(place), span)),
898                                     pat_span: span,
899                                 },
900                             )))
901                         };
902                         self.var_indices.insert(var, LocalsForNode::One(local));
903                     }
904                     _ => {
905                         scope = self.declare_bindings(
906                             scope,
907                             ast_body.span,
908                             &pattern,
909                             matches::ArmHasGuard(false),
910                             Some((Some(&place), span)),
911                         );
912                         unpack!(block = self.place_into_pattern(block, pattern, &place, false));
913                     }
914                 }
915                 self.source_scope = original_source_scope;
916             }
917         }
918
919         // Enter the argument pattern bindings source scope, if it exists.
920         if let Some(source_scope) = scope {
921             self.source_scope = source_scope;
922         }
923
924         let body = self.hir.mirror(ast_body);
925         self.into(&Place::return_place(), block, body)
926     }
927
928     fn set_correct_source_scope_for_arg(
929         &mut self,
930         arg_hir_id: hir::HirId,
931         original_source_scope: SourceScope,
932         pattern_span: Span,
933     ) {
934         let tcx = self.hir.tcx();
935         let current_root = tcx.maybe_lint_level_root_bounded(arg_hir_id, self.hir.root_lint_level);
936         let parent_root = tcx.maybe_lint_level_root_bounded(
937             self.source_scopes[original_source_scope]
938                 .local_data
939                 .as_ref()
940                 .assert_crate_local()
941                 .lint_root,
942             self.hir.root_lint_level,
943         );
944         if current_root != parent_root {
945             self.source_scope =
946                 self.new_source_scope(pattern_span, LintLevel::Explicit(current_root), None);
947         }
948     }
949
950     fn get_unit_temp(&mut self) -> Place<'tcx> {
951         match self.unit_temp {
952             Some(tmp) => tmp,
953             None => {
954                 let ty = self.hir.unit_ty();
955                 let fn_span = self.fn_span;
956                 let tmp = self.temp(ty, fn_span);
957                 self.unit_temp = Some(tmp);
958                 tmp
959             }
960         }
961     }
962
963     fn return_block(&mut self) -> BasicBlock {
964         match self.cached_return_block {
965             Some(rb) => rb,
966             None => {
967                 let rb = self.cfg.start_new_block();
968                 self.cached_return_block = Some(rb);
969                 rb
970             }
971         }
972     }
973 }
974
975 ///////////////////////////////////////////////////////////////////////////
976 // Builder methods are broken up into modules, depending on what kind
977 // of thing is being lowered. Note that they use the `unpack` macro
978 // above extensively.
979
980 mod block;
981 mod cfg;
982 mod expr;
983 mod into;
984 mod matches;
985 mod misc;
986 mod scope;