]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/build/mod.rs
Auto merge of #54265 - arielb1:civilize-proc-macros, r=alexcrichton
[rust.git] / src / librustc_mir / build / mod.rs
1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11
12 use build;
13 use build::scope::{CachedBlock, DropKind};
14 use hair::cx::Cx;
15 use hair::{LintLevel, BindingMode, PatternKind};
16 use rustc::hir;
17 use rustc::hir::Node;
18 use rustc::hir::def_id::{DefId, LocalDefId};
19 use rustc::middle::region;
20 use rustc::mir::*;
21 use rustc::mir::visit::{MutVisitor, TyContext};
22 use rustc::ty::{self, Ty, TyCtxt};
23 use rustc::ty::subst::Substs;
24 use rustc::util::nodemap::NodeMap;
25 use rustc_target::spec::PanicStrategy;
26 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
27 use shim;
28 use std::mem;
29 use std::u32;
30 use rustc_target::spec::abi::Abi;
31 use syntax::ast;
32 use syntax::attr::{self, UnwindAttr};
33 use syntax::symbol::keywords;
34 use syntax_pos::Span;
35 use transform::MirSource;
36 use util as mir_util;
37
38 /// Construct the MIR for a given def-id.
39 pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'tcx> {
40     let id = tcx.hir.as_local_node_id(def_id).unwrap();
41
42     // Figure out what primary body this item has.
43     let body_id = match tcx.hir.get(id) {
44         Node::Variant(variant) =>
45             return create_constructor_shim(tcx, id, &variant.node.data),
46         Node::StructCtor(ctor) =>
47             return create_constructor_shim(tcx, id, ctor),
48
49         _ => match tcx.hir.maybe_body_owned_by(id) {
50             Some(body) => body,
51             None => span_bug!(tcx.hir.span(id), "can't build MIR for {:?}", def_id),
52         },
53     };
54
55     tcx.infer_ctxt().enter(|infcx| {
56         let cx = Cx::new(&infcx, id);
57         let mut mir = if cx.tables().tainted_by_errors {
58             build::construct_error(cx, body_id)
59         } else if let hir::BodyOwnerKind::Fn = cx.body_owner_kind {
60             // fetch the fully liberated fn signature (that is, all bound
61             // types/lifetimes replaced)
62             let fn_hir_id = tcx.hir.node_to_hir_id(id);
63             let fn_sig = cx.tables().liberated_fn_sigs()[fn_hir_id].clone();
64
65             let ty = tcx.type_of(tcx.hir.local_def_id(id));
66             let mut abi = fn_sig.abi;
67             let implicit_argument = match ty.sty {
68                 ty::Closure(..) => {
69                     // HACK(eddyb) Avoid having RustCall on closures,
70                     // as it adds unnecessary (and wrong) auto-tupling.
71                     abi = Abi::Rust;
72                     Some(ArgInfo(liberated_closure_env_ty(tcx, id, body_id), None, None, None))
73                 }
74                 ty::Generator(..) => {
75                     let gen_ty = tcx.body_tables(body_id).node_id_to_type(fn_hir_id);
76                     Some(ArgInfo(gen_ty, None, None, None))
77                 }
78                 _ => None,
79             };
80
81             // FIXME: safety in closures
82             let safety = match fn_sig.unsafety {
83                 hir::Unsafety::Normal => Safety::Safe,
84                 hir::Unsafety::Unsafe => Safety::FnUnsafe,
85             };
86
87             let body = tcx.hir.body(body_id);
88             let explicit_arguments =
89                 body.arguments
90                     .iter()
91                     .enumerate()
92                     .map(|(index, arg)| {
93                         let owner_id = tcx.hir.body_owner(body_id);
94                         let opt_ty_info;
95                         let self_arg;
96                         if let Some(ref fn_decl) = tcx.hir.fn_decl(owner_id) {
97                             let ty_hir_id = fn_decl.inputs[index].hir_id;
98                             let ty_span = tcx.hir.span(tcx.hir.hir_to_node_id(ty_hir_id));
99                             opt_ty_info = Some(ty_span);
100                             self_arg = if index == 0 && fn_decl.has_implicit_self {
101                                 Some(ImplicitSelfBinding)
102                             } else {
103                                 None
104                             };
105                         } else {
106                             opt_ty_info = None;
107                             self_arg = None;
108                         }
109                         ArgInfo(fn_sig.inputs()[index], opt_ty_info, Some(&*arg.pat), self_arg)
110                     });
111
112             let arguments = implicit_argument.into_iter().chain(explicit_arguments);
113
114             let (yield_ty, return_ty) = if body.is_generator {
115                 let gen_sig = match ty.sty {
116                     ty::Generator(gen_def_id, gen_substs, ..) =>
117                         gen_substs.sig(gen_def_id, tcx),
118                     _ =>
119                         span_bug!(tcx.hir.span(id), "generator w/o generator type: {:?}", ty),
120                 };
121                 (Some(gen_sig.yield_ty), gen_sig.return_ty)
122             } else {
123                 (None, fn_sig.output())
124             };
125
126             build::construct_fn(cx, id, arguments, safety, abi,
127                                 return_ty, yield_ty, body)
128         } else {
129             build::construct_const(cx, body_id)
130         };
131
132         // Convert the Mir to global types.
133         let mut globalizer = GlobalizeMir {
134             tcx,
135             span: mir.span
136         };
137         globalizer.visit_mir(&mut mir);
138         let mir = unsafe {
139             mem::transmute::<Mir, Mir<'tcx>>(mir)
140         };
141
142         mir_util::dump_mir(tcx, None, "mir_map", &0,
143                            MirSource::item(def_id), &mir, |_, _| Ok(()) );
144
145         mir
146     })
147 }
148
149 /// A pass to lift all the types and substitutions in a Mir
150 /// to the global tcx. Sadly, we don't have a "folder" that
151 /// can change 'tcx so we have to transmute afterwards.
152 struct GlobalizeMir<'a, 'gcx: 'a> {
153     tcx: TyCtxt<'a, 'gcx, 'gcx>,
154     span: Span
155 }
156
157 impl<'a, 'gcx: 'tcx, 'tcx> MutVisitor<'tcx> for GlobalizeMir<'a, 'gcx> {
158     fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: TyContext) {
159         if let Some(lifted) = self.tcx.lift(ty) {
160             *ty = lifted;
161         } else {
162             span_bug!(self.span,
163                       "found type `{:?}` with inference types/regions in MIR",
164                       ty);
165         }
166     }
167
168     fn visit_region(&mut self, region: &mut ty::Region<'tcx>, _: Location) {
169         if let Some(lifted) = self.tcx.lift(region) {
170             *region = lifted;
171         } else {
172             span_bug!(self.span,
173                       "found region `{:?}` with inference types/regions in MIR",
174                       region);
175         }
176     }
177
178     fn visit_const(&mut self, constant: &mut &'tcx ty::Const<'tcx>, _: Location) {
179         if let Some(lifted) = self.tcx.lift(constant) {
180             *constant = lifted;
181         } else {
182             span_bug!(self.span,
183                       "found constant `{:?}` with inference types/regions in MIR",
184                       constant);
185         }
186     }
187
188     fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>, _: Location) {
189         if let Some(lifted) = self.tcx.lift(substs) {
190             *substs = lifted;
191         } else {
192             span_bug!(self.span,
193                       "found substs `{:?}` with inference types/regions in MIR",
194                       substs);
195         }
196     }
197 }
198
199 fn create_constructor_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
200                                      ctor_id: ast::NodeId,
201                                      v: &'tcx hir::VariantData)
202                                      -> Mir<'tcx>
203 {
204     let span = tcx.hir.span(ctor_id);
205     if let hir::VariantData::Tuple(ref fields, ctor_id) = *v {
206         tcx.infer_ctxt().enter(|infcx| {
207             let mut mir = shim::build_adt_ctor(&infcx, ctor_id, fields, span);
208
209             // Convert the Mir to global types.
210             let tcx = infcx.tcx.global_tcx();
211             let mut globalizer = GlobalizeMir {
212                 tcx,
213                 span: mir.span
214             };
215             globalizer.visit_mir(&mut mir);
216             let mir = unsafe {
217                 mem::transmute::<Mir, Mir<'tcx>>(mir)
218             };
219
220             mir_util::dump_mir(tcx, None, "mir_map", &0,
221                                MirSource::item(tcx.hir.local_def_id(ctor_id)),
222                                &mir, |_, _| Ok(()) );
223
224             mir
225         })
226     } else {
227         span_bug!(span, "attempting to create MIR for non-tuple variant {:?}", v);
228     }
229 }
230
231 ///////////////////////////////////////////////////////////////////////////
232 // BuildMir -- walks a crate, looking for fn items and methods to build MIR from
233
234 fn liberated_closure_env_ty<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
235                                             closure_expr_id: ast::NodeId,
236                                             body_id: hir::BodyId)
237                                             -> Ty<'tcx> {
238     let closure_expr_hir_id = tcx.hir.node_to_hir_id(closure_expr_id);
239     let closure_ty = tcx.body_tables(body_id).node_id_to_type(closure_expr_hir_id);
240
241     let (closure_def_id, closure_substs) = match closure_ty.sty {
242         ty::Closure(closure_def_id, closure_substs) => (closure_def_id, closure_substs),
243         _ => bug!("closure expr does not have closure type: {:?}", closure_ty)
244     };
245
246     let closure_env_ty = tcx.closure_env_ty(closure_def_id, closure_substs).unwrap();
247     tcx.liberate_late_bound_regions(closure_def_id, &closure_env_ty)
248 }
249
250 struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
251     hir: Cx<'a, 'gcx, 'tcx>,
252     cfg: CFG<'tcx>,
253
254     fn_span: Span,
255     arg_count: usize,
256
257     /// the current set of scopes, updated as we traverse;
258     /// see the `scope` module for more details
259     scopes: Vec<scope::Scope<'tcx>>,
260
261     /// The current unsafe block in scope, even if it is hidden by
262     /// a PushUnsafeBlock
263     unpushed_unsafe: Safety,
264
265     /// The number of `push_unsafe_block` levels in scope
266     push_unsafe_count: usize,
267
268     /// the current set of breakables; see the `scope` module for more
269     /// details
270     breakable_scopes: Vec<scope::BreakableScope<'tcx>>,
271
272     /// the vector of all scopes that we have created thus far;
273     /// we track this for debuginfo later
274     source_scopes: IndexVec<SourceScope, SourceScopeData>,
275     source_scope_local_data: IndexVec<SourceScope, SourceScopeLocalData>,
276     source_scope: SourceScope,
277
278     /// the guard-context: each time we build the guard expression for
279     /// a match arm, we push onto this stack, and then pop when we
280     /// finish building it.
281     guard_context: Vec<GuardFrame>,
282
283     /// Maps node ids of variable bindings to the `Local`s created for them.
284     /// (A match binding can have two locals; the 2nd is for the arm's guard.)
285     var_indices: NodeMap<LocalsForNode>,
286     local_decls: IndexVec<Local, LocalDecl<'tcx>>,
287     upvar_decls: Vec<UpvarDecl>,
288     unit_temp: Option<Place<'tcx>>,
289
290     /// cached block with the RESUME terminator; this is created
291     /// when first set of cleanups are built.
292     cached_resume_block: Option<BasicBlock>,
293     /// cached block with the RETURN terminator
294     cached_return_block: Option<BasicBlock>,
295     /// cached block with the UNREACHABLE terminator
296     cached_unreachable_block: Option<BasicBlock>,
297 }
298
299 impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
300     fn is_bound_var_in_guard(&self, id: ast::NodeId) -> bool {
301         self.guard_context.iter().any(|frame| frame.locals.iter().any(|local| local.id == id))
302     }
303
304     fn var_local_id(&self, id: ast::NodeId, for_guard: ForGuard) -> Local {
305         self.var_indices[&id].local_id(for_guard)
306     }
307 }
308
309 #[derive(Debug)]
310 enum LocalsForNode {
311     /// In the usual case, a node-id for an identifier maps to at most
312     /// one Local declaration.
313     One(Local),
314
315     /// The exceptional case is identifiers in a match arm's pattern
316     /// that are referenced in a guard of that match arm. For these,
317     /// we can have `2+k` Locals, where `k` is the number of candidate
318     /// patterns (separated by `|`) in the arm.
319     ///
320     /// * `for_arm_body` is the Local used in the arm body (which is
321     ///   just like the `One` case above),
322     ///
323     /// * `ref_for_guard` is the Local used in the arm's guard (which
324     ///   is a reference to a temp that is an alias of
325     ///   `for_arm_body`).
326     ///
327     /// * `vals_for_guard` is the `k` Locals; at most one of them will
328     ///   get initialized by the arm's execution, and after it is
329     ///   initialized, `ref_for_guard` will be assigned a reference to
330     ///   it.
331     ///
332     /// There reason we have `k` Locals rather than just 1 is to
333     /// accommodate some restrictions imposed by two-phase borrows,
334     /// which apply when we have a `ref mut` pattern.
335     ForGuard { vals_for_guard: Vec<Local>, ref_for_guard: Local, for_arm_body: Local },
336 }
337
338 #[derive(Debug)]
339 struct GuardFrameLocal {
340     id: ast::NodeId,
341 }
342
343 impl GuardFrameLocal {
344     fn new(id: ast::NodeId, _binding_mode: BindingMode) -> Self {
345         GuardFrameLocal {
346             id: id,
347         }
348     }
349 }
350
351 #[derive(Debug)]
352 struct GuardFrame {
353     /// These are the id's of names that are bound by patterns of the
354     /// arm of *this* guard.
355     ///
356     /// (Frames higher up the stack will have the id's bound in arms
357     /// further out, such as in a case like:
358     ///
359     /// match E1 {
360     ///      P1(id1) if (... (match E2 { P2(id2) if ... => B2 })) => B1,
361     /// }
362     ///
363     /// here, when building for FIXME
364     locals: Vec<GuardFrameLocal>,
365 }
366
367 /// ForGuard indicates whether we are talking about:
368 ///   1. the temp for a local binding used solely within guard expressions,
369 ///   2. the temp that holds reference to (1.), which is actually what the
370 ///      guard expressions see, or
371 ///   3. the temp for use outside of guard expressions.
372 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
373 enum ForGuard {
374     /// The `usize` identifies for which candidate pattern we want the
375     /// local binding. We keep a temp per-candidate to accommodate
376     /// two-phase borrows (see `LocalsForNode` documentation).
377     ValWithinGuard(usize),
378     RefWithinGuard,
379     OutsideGuard,
380 }
381
382 impl LocalsForNode {
383     fn local_id(&self, for_guard: ForGuard) -> Local {
384         match (self, for_guard) {
385             (&LocalsForNode::One(local_id), ForGuard::OutsideGuard) |
386             (&LocalsForNode::ForGuard { ref_for_guard: local_id, .. }, ForGuard::RefWithinGuard) |
387             (&LocalsForNode::ForGuard { for_arm_body: local_id, .. }, ForGuard::OutsideGuard) =>
388                 local_id,
389
390             (&LocalsForNode::ForGuard { ref vals_for_guard, .. },
391              ForGuard::ValWithinGuard(pat_idx)) =>
392                 vals_for_guard[pat_idx],
393
394             (&LocalsForNode::One(_), ForGuard::ValWithinGuard(_)) |
395             (&LocalsForNode::One(_), ForGuard::RefWithinGuard) =>
396                 bug!("anything with one local should never be within a guard."),
397         }
398     }
399 }
400
401 struct CFG<'tcx> {
402     basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
403 }
404
405 newtype_index! {
406     pub struct ScopeId { .. }
407 }
408
409 ///////////////////////////////////////////////////////////////////////////
410 /// The `BlockAnd` "monad" packages up the new basic block along with a
411 /// produced value (sometimes just unit, of course). The `unpack!`
412 /// macro (and methods below) makes working with `BlockAnd` much more
413 /// convenient.
414
415 #[must_use = "if you don't use one of these results, you're leaving a dangling edge"]
416 struct BlockAnd<T>(BasicBlock, T);
417
418 trait BlockAndExtension {
419     fn and<T>(self, v: T) -> BlockAnd<T>;
420     fn unit(self) -> BlockAnd<()>;
421 }
422
423 impl BlockAndExtension for BasicBlock {
424     fn and<T>(self, v: T) -> BlockAnd<T> {
425         BlockAnd(self, v)
426     }
427
428     fn unit(self) -> BlockAnd<()> {
429         BlockAnd(self, ())
430     }
431 }
432
433 /// Update a block pointer and return the value.
434 /// Use it like `let x = unpack!(block = self.foo(block, foo))`.
435 macro_rules! unpack {
436     ($x:ident = $c:expr) => {
437         {
438             let BlockAnd(b, v) = $c;
439             $x = b;
440             v
441         }
442     };
443
444     ($c:expr) => {
445         {
446             let BlockAnd(b, ()) = $c;
447             b
448         }
449     };
450 }
451
452 fn should_abort_on_panic<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
453                                          fn_def_id: DefId,
454                                          abi: Abi)
455                                          -> bool {
456     // Not callable from C, so we can safely unwind through these
457     if abi == Abi::Rust || abi == Abi::RustCall { return false; }
458
459     // We never unwind, so it's not relevant to stop an unwind
460     if tcx.sess.panic_strategy() != PanicStrategy::Unwind { return false; }
461
462     // We cannot add landing pads, so don't add one
463     if tcx.sess.no_landing_pads() { return false; }
464
465     // This is a special case: some functions have a C abi but are meant to
466     // unwind anyway. Don't stop them.
467     let attrs = &tcx.get_attrs(fn_def_id);
468     match attr::find_unwind_attr(Some(tcx.sess.diagnostic()), attrs) {
469         None => {
470             // FIXME(rust-lang/rust#48251) -- Had to disable
471             // abort-on-panic for backwards compatibility reasons.
472             false
473         }
474
475         Some(UnwindAttr::Allowed) => false,
476         Some(UnwindAttr::Aborts) => true,
477     }
478 }
479
480 ///////////////////////////////////////////////////////////////////////////
481 /// the main entry point for building MIR for a function
482
483 struct ImplicitSelfBinding;
484
485 struct ArgInfo<'gcx>(Ty<'gcx>,
486                      Option<Span>,
487                      Option<&'gcx hir::Pat>,
488                      Option<ImplicitSelfBinding>);
489
490 fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
491                                    fn_id: ast::NodeId,
492                                    arguments: A,
493                                    safety: Safety,
494                                    abi: Abi,
495                                    return_ty: Ty<'gcx>,
496                                    yield_ty: Option<Ty<'gcx>>,
497                                    body: &'gcx hir::Body)
498                                    -> Mir<'tcx>
499     where A: Iterator<Item=ArgInfo<'gcx>>
500 {
501     let arguments: Vec<_> = arguments.collect();
502
503     let tcx = hir.tcx();
504     let span = tcx.hir.span(fn_id);
505
506     // Gather the upvars of a closure, if any.
507     let upvar_decls: Vec<_> = tcx.with_freevars(fn_id, |freevars| {
508         freevars.iter().map(|fv| {
509             let var_id = fv.var_id();
510             let var_hir_id = tcx.hir.node_to_hir_id(var_id);
511             let closure_expr_id = tcx.hir.local_def_id(fn_id);
512             let capture = hir.tables().upvar_capture(ty::UpvarId {
513                 var_id: var_hir_id,
514                 closure_expr_id: LocalDefId::from_def_id(closure_expr_id),
515             });
516             let by_ref = match capture {
517                 ty::UpvarCapture::ByValue => false,
518                 ty::UpvarCapture::ByRef(..) => true
519             };
520             let mut decl = UpvarDecl {
521                 debug_name: keywords::Invalid.name(),
522                 var_hir_id: ClearCrossCrate::Set(var_hir_id),
523                 by_ref,
524                 mutability: Mutability::Not,
525             };
526             if let Some(Node::Binding(pat)) = tcx.hir.find(var_id) {
527                 if let hir::PatKind::Binding(_, _, ident, _) = pat.node {
528                     decl.debug_name = ident.name;
529
530                     if let Some(&bm) = hir.tables.pat_binding_modes().get(pat.hir_id) {
531                         if bm == ty::BindByValue(hir::MutMutable) {
532                             decl.mutability = Mutability::Mut;
533                         } else {
534                             decl.mutability = Mutability::Not;
535                         }
536                     } else {
537                         tcx.sess.delay_span_bug(pat.span, "missing binding mode");
538                     }
539                 }
540             }
541             decl
542         }).collect()
543     });
544
545     let mut builder = Builder::new(hir.clone(),
546         span,
547         arguments.len(),
548         safety,
549         return_ty,
550         upvar_decls);
551
552     let fn_def_id = tcx.hir.local_def_id(fn_id);
553     let call_site_scope = region::Scope {
554         id: body.value.hir_id.local_id,
555         data: region::ScopeData::CallSite
556     };
557     let arg_scope = region::Scope {
558         id: body.value.hir_id.local_id,
559         data: region::ScopeData::Arguments
560     };
561     let mut block = START_BLOCK;
562     let source_info = builder.source_info(span);
563     let call_site_s = (call_site_scope, source_info);
564     unpack!(block = builder.in_scope(call_site_s, LintLevel::Inherited, block, |builder| {
565         if should_abort_on_panic(tcx, fn_def_id, abi) {
566             builder.schedule_abort();
567         }
568
569         let arg_scope_s = (arg_scope, source_info);
570         unpack!(block = builder.in_scope(arg_scope_s, LintLevel::Inherited, block, |builder| {
571             builder.args_and_body(block, &arguments, arg_scope, &body.value)
572         }));
573         // Attribute epilogue to function's closing brace
574         let fn_end = span.shrink_to_hi();
575         let source_info = builder.source_info(fn_end);
576         let return_block = builder.return_block();
577         builder.cfg.terminate(block, source_info,
578                               TerminatorKind::Goto { target: return_block });
579         builder.cfg.terminate(return_block, source_info,
580                               TerminatorKind::Return);
581         // Attribute any unreachable codepaths to the function's closing brace
582         if let Some(unreachable_block) = builder.cached_unreachable_block {
583             builder.cfg.terminate(unreachable_block, source_info,
584                                   TerminatorKind::Unreachable);
585         }
586         return_block.unit()
587     }));
588     assert_eq!(block, builder.return_block());
589
590     let mut spread_arg = None;
591     if abi == Abi::RustCall {
592         // RustCall pseudo-ABI untuples the last argument.
593         spread_arg = Some(Local::new(arguments.len()));
594     }
595     let closure_expr_id = tcx.hir.local_def_id(fn_id);
596     info!("fn_id {:?} has attrs {:?}", closure_expr_id,
597           tcx.get_attrs(closure_expr_id));
598
599     let mut mir = builder.finish(yield_ty);
600     mir.spread_arg = spread_arg;
601     mir
602 }
603
604 fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
605                                    body_id: hir::BodyId)
606                                    -> Mir<'tcx> {
607     let tcx = hir.tcx();
608     let ast_expr = &tcx.hir.body(body_id).value;
609     let ty = hir.tables().expr_ty_adjusted(ast_expr);
610     let owner_id = tcx.hir.body_owner(body_id);
611     let span = tcx.hir.span(owner_id);
612     let mut builder = Builder::new(hir.clone(), span, 0, Safety::Safe, ty, vec![]);
613
614     let mut block = START_BLOCK;
615     let expr = builder.hir.mirror(ast_expr);
616     unpack!(block = builder.into_expr(&Place::Local(RETURN_PLACE), block, expr));
617
618     let source_info = builder.source_info(span);
619     builder.cfg.terminate(block, source_info, TerminatorKind::Return);
620
621     // Constants can't `return` so a return block should not be created.
622     assert_eq!(builder.cached_return_block, None);
623
624     // Constants may be match expressions in which case an unreachable block may
625     // be created, so terminate it properly.
626     if let Some(unreachable_block) = builder.cached_unreachable_block {
627         builder.cfg.terminate(unreachable_block, source_info,
628                               TerminatorKind::Unreachable);
629     }
630
631     builder.finish(None)
632 }
633
634 fn construct_error<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
635                                    body_id: hir::BodyId)
636                                    -> Mir<'tcx> {
637     let owner_id = hir.tcx().hir.body_owner(body_id);
638     let span = hir.tcx().hir.span(owner_id);
639     let ty = hir.tcx().types.err;
640     let mut builder = Builder::new(hir, span, 0, Safety::Safe, ty, vec![]);
641     let source_info = builder.source_info(span);
642     builder.cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable);
643     builder.finish(None)
644 }
645
646 impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
647     fn new(hir: Cx<'a, 'gcx, 'tcx>,
648            span: Span,
649            arg_count: usize,
650            safety: Safety,
651            return_ty: Ty<'tcx>,
652            upvar_decls: Vec<UpvarDecl>)
653            -> Builder<'a, 'gcx, 'tcx> {
654         let lint_level = LintLevel::Explicit(hir.root_lint_level);
655         let mut builder = Builder {
656             hir,
657             cfg: CFG { basic_blocks: IndexVec::new() },
658             fn_span: span,
659             arg_count,
660             scopes: vec![],
661             source_scopes: IndexVec::new(),
662             source_scope: OUTERMOST_SOURCE_SCOPE,
663             source_scope_local_data: IndexVec::new(),
664             guard_context: vec![],
665             push_unsafe_count: 0,
666             unpushed_unsafe: safety,
667             breakable_scopes: vec![],
668             local_decls: IndexVec::from_elem_n(LocalDecl::new_return_place(return_ty,
669                                                                              span), 1),
670             upvar_decls,
671             var_indices: NodeMap(),
672             unit_temp: None,
673             cached_resume_block: None,
674             cached_return_block: None,
675             cached_unreachable_block: None,
676         };
677
678         assert_eq!(builder.cfg.start_new_block(), START_BLOCK);
679         assert_eq!(
680             builder.new_source_scope(span, lint_level, Some(safety)),
681             OUTERMOST_SOURCE_SCOPE);
682         builder.source_scopes[OUTERMOST_SOURCE_SCOPE].parent_scope = None;
683
684         builder
685     }
686
687     fn finish(self,
688               yield_ty: Option<Ty<'tcx>>)
689               -> Mir<'tcx> {
690         for (index, block) in self.cfg.basic_blocks.iter().enumerate() {
691             if block.terminator.is_none() {
692                 span_bug!(self.fn_span, "no terminator on block {:?}", index);
693             }
694         }
695
696         Mir::new(self.cfg.basic_blocks,
697                  self.source_scopes,
698                  ClearCrossCrate::Set(self.source_scope_local_data),
699                  IndexVec::new(),
700                  yield_ty,
701                  self.local_decls,
702                  self.arg_count,
703                  self.upvar_decls,
704                  self.fn_span
705         )
706     }
707
708     fn args_and_body(&mut self,
709                      mut block: BasicBlock,
710                      arguments: &[ArgInfo<'gcx>],
711                      argument_scope: region::Scope,
712                      ast_body: &'gcx hir::Expr)
713                      -> BlockAnd<()>
714     {
715         // Allocate locals for the function arguments
716         for &ArgInfo(ty, _, pattern, _) in arguments.iter() {
717             // If this is a simple binding pattern, give the local a name for
718             // debuginfo and so that error reporting knows that this is a user
719             // variable. For any other pattern the pattern introduces new
720             // variables which will be named instead.
721             let mut name = None;
722             if let Some(pat) = pattern {
723                 match pat.node {
724                     hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, ident, _)
725                     | hir::PatKind::Binding(hir::BindingAnnotation::Mutable, _, ident, _) => {
726                         name = Some(ident.name);
727                     }
728                     _ => (),
729                 }
730             }
731
732             let source_info = SourceInfo {
733                 scope: OUTERMOST_SOURCE_SCOPE,
734                 span: pattern.map_or(self.fn_span, |pat| pat.span)
735             };
736             self.local_decls.push(LocalDecl {
737                 mutability: Mutability::Mut,
738                 ty,
739                 user_ty: None,
740                 source_info,
741                 visibility_scope: source_info.scope,
742                 name,
743                 internal: false,
744                 is_user_variable: None,
745             });
746         }
747
748         let mut scope = None;
749         // Bind the argument patterns
750         for (index, arg_info) in arguments.iter().enumerate() {
751             // Function arguments always get the first Local indices after the return place
752             let local = Local::new(index + 1);
753             let place = Place::Local(local);
754             let &ArgInfo(ty, opt_ty_info, pattern, ref self_binding) = arg_info;
755
756             if let Some(pattern) = pattern {
757                 let pattern = self.hir.pattern_from_hir(pattern);
758                 let span = pattern.span;
759
760                 match *pattern.kind {
761                     // Don't introduce extra copies for simple bindings
762                     PatternKind::Binding { mutability, var, mode: BindingMode::ByValue, .. } => {
763                         self.local_decls[local].mutability = mutability;
764                         self.local_decls[local].is_user_variable =
765                             if let Some(ImplicitSelfBinding) = self_binding {
766                                 Some(ClearCrossCrate::Set(BindingForm::ImplicitSelf))
767                             } else {
768                                 let binding_mode = ty::BindingMode::BindByValue(mutability.into());
769                                 Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
770                                     binding_mode,
771                                     opt_ty_info,
772                                     opt_match_place: Some((Some(place.clone()), span)),
773                                     pat_span: span,
774                                 })))
775                             };
776                         self.var_indices.insert(var, LocalsForNode::One(local));
777                     }
778                     _ => {
779                         scope = self.declare_bindings(scope, ast_body.span,
780                                                       LintLevel::Inherited, &[pattern.clone()],
781                                                       matches::ArmHasGuard(false),
782                                                       Some((Some(&place), span)));
783                         unpack!(block = self.place_into_pattern(block, pattern, &place, false));
784                     }
785                 }
786             }
787
788             // Make sure we drop (parts of) the argument even when not matched on.
789             self.schedule_drop(
790                 pattern.as_ref().map_or(ast_body.span, |pat| pat.span),
791                 argument_scope, &place, ty,
792                 DropKind::Value { cached_block: CachedBlock::default() },
793             );
794         }
795
796         // Enter the argument pattern bindings source scope, if it exists.
797         if let Some(source_scope) = scope {
798             self.source_scope = source_scope;
799         }
800
801         let body = self.hir.mirror(ast_body);
802         self.into(&Place::Local(RETURN_PLACE), block, body)
803     }
804
805     fn get_unit_temp(&mut self) -> Place<'tcx> {
806         match self.unit_temp {
807             Some(ref tmp) => tmp.clone(),
808             None => {
809                 let ty = self.hir.unit_ty();
810                 let fn_span = self.fn_span;
811                 let tmp = self.temp(ty, fn_span);
812                 self.unit_temp = Some(tmp.clone());
813                 tmp
814             }
815         }
816     }
817
818     fn return_block(&mut self) -> BasicBlock {
819         match self.cached_return_block {
820             Some(rb) => rb,
821             None => {
822                 let rb = self.cfg.start_new_block();
823                 self.cached_return_block = Some(rb);
824                 rb
825             }
826         }
827     }
828
829     fn unreachable_block(&mut self) -> BasicBlock {
830         match self.cached_unreachable_block {
831             Some(ub) => ub,
832             None => {
833                 let ub = self.cfg.start_new_block();
834                 self.cached_unreachable_block = Some(ub);
835                 ub
836             }
837         }
838     }
839 }
840
841 ///////////////////////////////////////////////////////////////////////////
842 // Builder methods are broken up into modules, depending on what kind
843 // of thing is being lowered. Note that they use the `unpack` macro
844 // above extensively.
845
846 mod block;
847 mod cfg;
848 mod expr;
849 mod into;
850 mod matches;
851 mod misc;
852 mod scope;