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