]> git.lizzy.rs Git - rust.git/blob - src/librustc/mir/mod.rs
96ccc3ba50078a8174bfb7c323dfb63b151cfdf1
[rust.git] / src / librustc / mir / mod.rs
1 // Copyright 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 //! MIR datatypes and passes. See [the README](README.md) for details.
12
13 use graphviz::IntoCow;
14 use middle::const_val::ConstVal;
15 use middle::region::CodeExtent;
16 use rustc_const_math::{ConstUsize, ConstInt, ConstMathErr};
17 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
18 use rustc_data_structures::control_flow_graph::dominators::{Dominators, dominators};
19 use rustc_data_structures::control_flow_graph::{GraphPredecessors, GraphSuccessors};
20 use rustc_data_structures::control_flow_graph::ControlFlowGraph;
21 use hir::def::CtorKind;
22 use hir::def_id::DefId;
23 use ty::subst::{Subst, Substs};
24 use ty::{self, AdtDef, ClosureSubsts, Region, Ty};
25 use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
26 use util::ppaux;
27 use rustc_back::slice;
28 use hir::InlineAsm;
29 use std::ascii;
30 use std::borrow::{Cow};
31 use std::cell::Ref;
32 use std::fmt::{self, Debug, Formatter, Write};
33 use std::{iter, u32};
34 use std::ops::{Index, IndexMut};
35 use std::vec::IntoIter;
36 use syntax::ast::Name;
37 use syntax_pos::Span;
38
39 mod cache;
40 pub mod tcx;
41 pub mod visit;
42 pub mod transform;
43 pub mod traversal;
44
45 macro_rules! newtype_index {
46     ($name:ident, $debug_name:expr) => (
47         #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord,
48          RustcEncodable, RustcDecodable)]
49         pub struct $name(u32);
50
51         impl Idx for $name {
52             fn new(value: usize) -> Self {
53                 assert!(value < (u32::MAX) as usize);
54                 $name(value as u32)
55             }
56             fn index(self) -> usize {
57                 self.0 as usize
58             }
59         }
60
61         impl Debug for $name {
62             fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
63                 write!(fmt, "{}{}", $debug_name, self.0)
64             }
65         }
66     )
67 }
68
69 /// Lowered representation of a single function.
70 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
71 pub struct Mir<'tcx> {
72     /// List of basic blocks. References to basic block use a newtyped index type `BasicBlock`
73     /// that indexes into this vector.
74     basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
75
76     /// List of visibility (lexical) scopes; these are referenced by statements
77     /// and used (eventually) for debuginfo. Indexed by a `VisibilityScope`.
78     pub visibility_scopes: IndexVec<VisibilityScope, VisibilityScopeData>,
79
80     /// Rvalues promoted from this function, such as borrows of constants.
81     /// Each of them is the Mir of a constant with the fn's type parameters
82     /// in scope, but a separate set of locals.
83     pub promoted: IndexVec<Promoted, Mir<'tcx>>,
84
85     /// Return type of the function.
86     pub return_ty: Ty<'tcx>,
87
88     /// Declarations of locals.
89     ///
90     /// The first local is the return value pointer, followed by `arg_count`
91     /// locals for the function arguments, followed by any user-declared
92     /// variables and temporaries.
93     pub local_decls: IndexVec<Local, LocalDecl<'tcx>>,
94
95     /// Number of arguments this function takes.
96     ///
97     /// Starting at local 1, `arg_count` locals will be provided by the caller
98     /// and can be assumed to be initialized.
99     ///
100     /// If this MIR was built for a constant, this will be 0.
101     pub arg_count: usize,
102
103     /// Names and capture modes of all the closure upvars, assuming
104     /// the first argument is either the closure or a reference to it.
105     pub upvar_decls: Vec<UpvarDecl>,
106
107     /// Mark an argument local (which must be a tuple) as getting passed as
108     /// its individual components at the LLVM level.
109     ///
110     /// This is used for the "rust-call" ABI.
111     pub spread_arg: Option<Local>,
112
113     /// A span representing this MIR, for error reporting
114     pub span: Span,
115
116     /// A cache for various calculations
117     cache: cache::Cache
118 }
119
120 /// where execution begins
121 pub const START_BLOCK: BasicBlock = BasicBlock(0);
122
123 impl<'tcx> Mir<'tcx> {
124     pub fn new(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
125                visibility_scopes: IndexVec<VisibilityScope, VisibilityScopeData>,
126                promoted: IndexVec<Promoted, Mir<'tcx>>,
127                return_ty: Ty<'tcx>,
128                local_decls: IndexVec<Local, LocalDecl<'tcx>>,
129                arg_count: usize,
130                upvar_decls: Vec<UpvarDecl>,
131                span: Span) -> Self
132     {
133         // We need `arg_count` locals, and one for the return pointer
134         assert!(local_decls.len() >= arg_count + 1,
135             "expected at least {} locals, got {}", arg_count + 1, local_decls.len());
136         assert_eq!(local_decls[RETURN_POINTER].ty, return_ty);
137
138         Mir {
139             basic_blocks,
140             visibility_scopes,
141             promoted,
142             return_ty,
143             local_decls,
144             arg_count,
145             upvar_decls,
146             spread_arg: None,
147             span,
148             cache: cache::Cache::new()
149         }
150     }
151
152     #[inline]
153     pub fn basic_blocks(&self) -> &IndexVec<BasicBlock, BasicBlockData<'tcx>> {
154         &self.basic_blocks
155     }
156
157     #[inline]
158     pub fn basic_blocks_mut(&mut self) -> &mut IndexVec<BasicBlock, BasicBlockData<'tcx>> {
159         self.cache.invalidate();
160         &mut self.basic_blocks
161     }
162
163     #[inline]
164     pub fn predecessors(&self) -> Ref<IndexVec<BasicBlock, Vec<BasicBlock>>> {
165         self.cache.predecessors(self)
166     }
167
168     #[inline]
169     pub fn predecessors_for(&self, bb: BasicBlock) -> Ref<Vec<BasicBlock>> {
170         Ref::map(self.predecessors(), |p| &p[bb])
171     }
172
173     #[inline]
174     pub fn dominators(&self) -> Dominators<BasicBlock> {
175         dominators(self)
176     }
177
178     #[inline]
179     pub fn local_kind(&self, local: Local) -> LocalKind {
180         let index = local.0 as usize;
181         if index == 0 {
182             debug_assert!(self.local_decls[local].mutability == Mutability::Mut,
183                           "return pointer should be mutable");
184
185             LocalKind::ReturnPointer
186         } else if index < self.arg_count + 1 {
187             LocalKind::Arg
188         } else if self.local_decls[local].name.is_some() {
189             LocalKind::Var
190         } else {
191             debug_assert!(self.local_decls[local].mutability == Mutability::Mut,
192                           "temp should be mutable");
193
194             LocalKind::Temp
195         }
196     }
197
198     /// Returns an iterator over all temporaries.
199     #[inline]
200     pub fn temps_iter<'a>(&'a self) -> impl Iterator<Item=Local> + 'a {
201         (self.arg_count+1..self.local_decls.len()).filter_map(move |index| {
202             let local = Local::new(index);
203             if self.local_decls[local].is_user_variable {
204                 None
205             } else {
206                 Some(local)
207             }
208         })
209     }
210
211     /// Returns an iterator over all user-declared locals.
212     #[inline]
213     pub fn vars_iter<'a>(&'a self) -> impl Iterator<Item=Local> + 'a {
214         (self.arg_count+1..self.local_decls.len()).filter_map(move |index| {
215             let local = Local::new(index);
216             if self.local_decls[local].is_user_variable {
217                 Some(local)
218             } else {
219                 None
220             }
221         })
222     }
223
224     /// Returns an iterator over all function arguments.
225     #[inline]
226     pub fn args_iter(&self) -> impl Iterator<Item=Local> {
227         let arg_count = self.arg_count;
228         (1..arg_count+1).map(Local::new)
229     }
230
231     /// Returns an iterator over all user-defined variables and compiler-generated temporaries (all
232     /// locals that are neither arguments nor the return pointer).
233     #[inline]
234     pub fn vars_and_temps_iter(&self) -> impl Iterator<Item=Local> {
235         let arg_count = self.arg_count;
236         let local_count = self.local_decls.len();
237         (arg_count+1..local_count).map(Local::new)
238     }
239
240     /// Changes a statement to a nop. This is both faster than deleting instructions and avoids
241     /// invalidating statement indices in `Location`s.
242     pub fn make_statement_nop(&mut self, location: Location) {
243         let block = &mut self[location.block];
244         debug_assert!(location.statement_index < block.statements.len());
245         block.statements[location.statement_index].make_nop()
246     }
247 }
248
249 impl_stable_hash_for!(struct Mir<'tcx> {
250     basic_blocks,
251     visibility_scopes,
252     promoted,
253     return_ty,
254     local_decls,
255     arg_count,
256     upvar_decls,
257     spread_arg,
258     span,
259     cache
260 });
261
262 impl<'tcx> Index<BasicBlock> for Mir<'tcx> {
263     type Output = BasicBlockData<'tcx>;
264
265     #[inline]
266     fn index(&self, index: BasicBlock) -> &BasicBlockData<'tcx> {
267         &self.basic_blocks()[index]
268     }
269 }
270
271 impl<'tcx> IndexMut<BasicBlock> for Mir<'tcx> {
272     #[inline]
273     fn index_mut(&mut self, index: BasicBlock) -> &mut BasicBlockData<'tcx> {
274         &mut self.basic_blocks_mut()[index]
275     }
276 }
277
278 /// Grouped information about the source code origin of a MIR entity.
279 /// Intended to be inspected by diagnostics and debuginfo.
280 /// Most passes can work with it as a whole, within a single function.
281 #[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
282 pub struct SourceInfo {
283     /// Source span for the AST pertaining to this MIR entity.
284     pub span: Span,
285
286     /// The lexical visibility scope, i.e. which bindings can be seen.
287     pub scope: VisibilityScope
288 }
289
290 ///////////////////////////////////////////////////////////////////////////
291 // Mutability and borrow kinds
292
293 #[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
294 pub enum Mutability {
295     Mut,
296     Not,
297 }
298
299 #[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
300 pub enum BorrowKind {
301     /// Data must be immutable and is aliasable.
302     Shared,
303
304     /// Data must be immutable but not aliasable.  This kind of borrow
305     /// cannot currently be expressed by the user and is used only in
306     /// implicit closure bindings. It is needed when you the closure
307     /// is borrowing or mutating a mutable referent, e.g.:
308     ///
309     ///    let x: &mut isize = ...;
310     ///    let y = || *x += 5;
311     ///
312     /// If we were to try to translate this closure into a more explicit
313     /// form, we'd encounter an error with the code as written:
314     ///
315     ///    struct Env { x: & &mut isize }
316     ///    let x: &mut isize = ...;
317     ///    let y = (&mut Env { &x }, fn_ptr);  // Closure is pair of env and fn
318     ///    fn fn_ptr(env: &mut Env) { **env.x += 5; }
319     ///
320     /// This is then illegal because you cannot mutate a `&mut` found
321     /// in an aliasable location. To solve, you'd have to translate with
322     /// an `&mut` borrow:
323     ///
324     ///    struct Env { x: & &mut isize }
325     ///    let x: &mut isize = ...;
326     ///    let y = (&mut Env { &mut x }, fn_ptr); // changed from &x to &mut x
327     ///    fn fn_ptr(env: &mut Env) { **env.x += 5; }
328     ///
329     /// Now the assignment to `**env.x` is legal, but creating a
330     /// mutable pointer to `x` is not because `x` is not mutable. We
331     /// could fix this by declaring `x` as `let mut x`. This is ok in
332     /// user code, if awkward, but extra weird for closures, since the
333     /// borrow is hidden.
334     ///
335     /// So we introduce a "unique imm" borrow -- the referent is
336     /// immutable, but not aliasable. This solves the problem. For
337     /// simplicity, we don't give users the way to express this
338     /// borrow, it's just used when translating closures.
339     Unique,
340
341     /// Data is mutable and not aliasable.
342     Mut,
343 }
344
345 ///////////////////////////////////////////////////////////////////////////
346 // Variables and temps
347
348 newtype_index!(Local, "_");
349
350 pub const RETURN_POINTER: Local = Local(0);
351
352 /// Classifies locals into categories. See `Mir::local_kind`.
353 #[derive(PartialEq, Eq, Debug)]
354 pub enum LocalKind {
355     /// User-declared variable binding
356     Var,
357     /// Compiler-introduced temporary
358     Temp,
359     /// Function argument
360     Arg,
361     /// Location of function's return value
362     ReturnPointer,
363 }
364
365 /// A MIR local.
366 ///
367 /// This can be a binding declared by the user, a temporary inserted by the compiler, a function
368 /// argument, or the return pointer.
369 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
370 pub struct LocalDecl<'tcx> {
371     /// `let mut x` vs `let x`.
372     ///
373     /// Temporaries and the return pointer are always mutable.
374     pub mutability: Mutability,
375
376     /// True if this corresponds to a user-declared local variable.
377     pub is_user_variable: bool,
378
379     /// Type of this local.
380     pub ty: Ty<'tcx>,
381
382     /// Name of the local, used in debuginfo and pretty-printing.
383     ///
384     /// Note that function arguments can also have this set to `Some(_)`
385     /// to generate better debuginfo.
386     pub name: Option<Name>,
387
388     /// Source info of the local.
389     pub source_info: SourceInfo,
390 }
391
392 impl<'tcx> LocalDecl<'tcx> {
393     /// Create a new `LocalDecl` for a temporary.
394     #[inline]
395     pub fn new_temp(ty: Ty<'tcx>, span: Span) -> Self {
396         LocalDecl {
397             mutability: Mutability::Mut,
398             ty,
399             name: None,
400             source_info: SourceInfo {
401                 span,
402                 scope: ARGUMENT_VISIBILITY_SCOPE
403             },
404             is_user_variable: false
405         }
406     }
407
408     /// Builds a `LocalDecl` for the return pointer.
409     ///
410     /// This must be inserted into the `local_decls` list as the first local.
411     #[inline]
412     pub fn new_return_pointer(return_ty: Ty, span: Span) -> LocalDecl {
413         LocalDecl {
414             mutability: Mutability::Mut,
415             ty: return_ty,
416             source_info: SourceInfo {
417                 span,
418                 scope: ARGUMENT_VISIBILITY_SCOPE
419             },
420             name: None,     // FIXME maybe we do want some name here?
421             is_user_variable: false
422         }
423     }
424 }
425
426 /// A closure capture, with its name and mode.
427 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
428 pub struct UpvarDecl {
429     pub debug_name: Name,
430
431     /// If true, the capture is behind a reference.
432     pub by_ref: bool
433 }
434
435 ///////////////////////////////////////////////////////////////////////////
436 // BasicBlock
437
438 newtype_index!(BasicBlock, "bb");
439
440 ///////////////////////////////////////////////////////////////////////////
441 // BasicBlockData and Terminator
442
443 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
444 pub struct BasicBlockData<'tcx> {
445     /// List of statements in this block.
446     pub statements: Vec<Statement<'tcx>>,
447
448     /// Terminator for this block.
449     ///
450     /// NB. This should generally ONLY be `None` during construction.
451     /// Therefore, you should generally access it via the
452     /// `terminator()` or `terminator_mut()` methods. The only
453     /// exception is that certain passes, such as `simplify_cfg`, swap
454     /// out the terminator temporarily with `None` while they continue
455     /// to recurse over the set of basic blocks.
456     pub terminator: Option<Terminator<'tcx>>,
457
458     /// If true, this block lies on an unwind path. This is used
459     /// during trans where distinct kinds of basic blocks may be
460     /// generated (particularly for MSVC cleanup). Unwind blocks must
461     /// only branch to other unwind blocks.
462     pub is_cleanup: bool,
463 }
464
465 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
466 pub struct Terminator<'tcx> {
467     pub source_info: SourceInfo,
468     pub kind: TerminatorKind<'tcx>
469 }
470
471 #[derive(Clone, RustcEncodable, RustcDecodable)]
472 pub enum TerminatorKind<'tcx> {
473     /// block should have one successor in the graph; we jump there
474     Goto {
475         target: BasicBlock,
476     },
477
478     /// operand evaluates to an integer; jump depending on its value
479     /// to one of the targets, and otherwise fallback to `otherwise`
480     SwitchInt {
481         /// discriminant value being tested
482         discr: Operand<'tcx>,
483
484         /// type of value being tested
485         switch_ty: Ty<'tcx>,
486
487         /// Possible values. The locations to branch to in each case
488         /// are found in the corresponding indices from the `targets` vector.
489         values: Cow<'tcx, [ConstInt]>,
490
491         /// Possible branch sites. The last element of this vector is used
492         /// for the otherwise branch, so targets.len() == values.len() + 1
493         /// should hold.
494         // This invariant is quite non-obvious and also could be improved.
495         // One way to make this invariant is to have something like this instead:
496         //
497         // branches: Vec<(ConstInt, BasicBlock)>,
498         // otherwise: Option<BasicBlock> // exhaustive if None
499         //
500         // However we’ve decided to keep this as-is until we figure a case
501         // where some other approach seems to be strictly better than other.
502         targets: Vec<BasicBlock>,
503     },
504
505     /// Indicates that the landing pad is finished and unwinding should
506     /// continue. Emitted by build::scope::diverge_cleanup.
507     Resume,
508
509     /// Indicates a normal return. The return pointer lvalue should
510     /// have been filled in by now. This should occur at most once.
511     Return,
512
513     /// Indicates a terminator that can never be reached.
514     Unreachable,
515
516     /// Drop the Lvalue
517     Drop {
518         location: Lvalue<'tcx>,
519         target: BasicBlock,
520         unwind: Option<BasicBlock>
521     },
522
523     /// Drop the Lvalue and assign the new value over it
524     DropAndReplace {
525         location: Lvalue<'tcx>,
526         value: Operand<'tcx>,
527         target: BasicBlock,
528         unwind: Option<BasicBlock>,
529     },
530
531     /// Block ends with a call of a converging function
532     Call {
533         /// The function that’s being called
534         func: Operand<'tcx>,
535         /// Arguments the function is called with
536         args: Vec<Operand<'tcx>>,
537         /// Destination for the return value. If some, the call is converging.
538         destination: Option<(Lvalue<'tcx>, BasicBlock)>,
539         /// Cleanups to be done if the call unwinds.
540         cleanup: Option<BasicBlock>
541     },
542
543     /// Jump to the target if the condition has the expected value,
544     /// otherwise panic with a message and a cleanup target.
545     Assert {
546         cond: Operand<'tcx>,
547         expected: bool,
548         msg: AssertMessage<'tcx>,
549         target: BasicBlock,
550         cleanup: Option<BasicBlock>
551     }
552 }
553
554 impl<'tcx> Terminator<'tcx> {
555     pub fn successors(&self) -> Cow<[BasicBlock]> {
556         self.kind.successors()
557     }
558
559     pub fn successors_mut(&mut self) -> Vec<&mut BasicBlock> {
560         self.kind.successors_mut()
561     }
562 }
563
564 impl<'tcx> TerminatorKind<'tcx> {
565     pub fn if_<'a, 'gcx>(tcx: ty::TyCtxt<'a, 'gcx, 'tcx>, cond: Operand<'tcx>,
566                          t: BasicBlock, f: BasicBlock) -> TerminatorKind<'tcx> {
567         static BOOL_SWITCH_FALSE: &'static [ConstInt] = &[ConstInt::U8(0)];
568         TerminatorKind::SwitchInt {
569             discr: cond,
570             switch_ty: tcx.types.bool,
571             values: From::from(BOOL_SWITCH_FALSE),
572             targets: vec![f, t],
573         }
574     }
575
576     pub fn successors(&self) -> Cow<[BasicBlock]> {
577         use self::TerminatorKind::*;
578         match *self {
579             Goto { target: ref b } => slice::ref_slice(b).into_cow(),
580             SwitchInt { targets: ref b, .. } => b[..].into_cow(),
581             Resume => (&[]).into_cow(),
582             Return => (&[]).into_cow(),
583             Unreachable => (&[]).into_cow(),
584             Call { destination: Some((_, t)), cleanup: Some(c), .. } => vec![t, c].into_cow(),
585             Call { destination: Some((_, ref t)), cleanup: None, .. } =>
586                 slice::ref_slice(t).into_cow(),
587             Call { destination: None, cleanup: Some(ref c), .. } => slice::ref_slice(c).into_cow(),
588             Call { destination: None, cleanup: None, .. } => (&[]).into_cow(),
589             DropAndReplace { target, unwind: Some(unwind), .. } |
590             Drop { target, unwind: Some(unwind), .. } => {
591                 vec![target, unwind].into_cow()
592             }
593             DropAndReplace { ref target, unwind: None, .. } |
594             Drop { ref target, unwind: None, .. } => {
595                 slice::ref_slice(target).into_cow()
596             }
597             Assert { target, cleanup: Some(unwind), .. } => vec![target, unwind].into_cow(),
598             Assert { ref target, .. } => slice::ref_slice(target).into_cow(),
599         }
600     }
601
602     // FIXME: no mootable cow. I’m honestly not sure what a “cow” between `&mut [BasicBlock]` and
603     // `Vec<&mut BasicBlock>` would look like in the first place.
604     pub fn successors_mut(&mut self) -> Vec<&mut BasicBlock> {
605         use self::TerminatorKind::*;
606         match *self {
607             Goto { target: ref mut b } => vec![b],
608             SwitchInt { targets: ref mut b, .. } => b.iter_mut().collect(),
609             Resume => Vec::new(),
610             Return => Vec::new(),
611             Unreachable => Vec::new(),
612             Call { destination: Some((_, ref mut t)), cleanup: Some(ref mut c), .. } => vec![t, c],
613             Call { destination: Some((_, ref mut t)), cleanup: None, .. } => vec![t],
614             Call { destination: None, cleanup: Some(ref mut c), .. } => vec![c],
615             Call { destination: None, cleanup: None, .. } => vec![],
616             DropAndReplace { ref mut target, unwind: Some(ref mut unwind), .. } |
617             Drop { ref mut target, unwind: Some(ref mut unwind), .. } => vec![target, unwind],
618             DropAndReplace { ref mut target, unwind: None, .. } |
619             Drop { ref mut target, unwind: None, .. } => {
620                 vec![target]
621             }
622             Assert { ref mut target, cleanup: Some(ref mut unwind), .. } => vec![target, unwind],
623             Assert { ref mut target, .. } => vec![target]
624         }
625     }
626 }
627
628 impl<'tcx> BasicBlockData<'tcx> {
629     pub fn new(terminator: Option<Terminator<'tcx>>) -> BasicBlockData<'tcx> {
630         BasicBlockData {
631             statements: vec![],
632             terminator,
633             is_cleanup: false,
634         }
635     }
636
637     /// Accessor for terminator.
638     ///
639     /// Terminator may not be None after construction of the basic block is complete. This accessor
640     /// provides a convenience way to reach the terminator.
641     pub fn terminator(&self) -> &Terminator<'tcx> {
642         self.terminator.as_ref().expect("invalid terminator state")
643     }
644
645     pub fn terminator_mut(&mut self) -> &mut Terminator<'tcx> {
646         self.terminator.as_mut().expect("invalid terminator state")
647     }
648 }
649
650 impl<'tcx> Debug for TerminatorKind<'tcx> {
651     fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
652         self.fmt_head(fmt)?;
653         let successors = self.successors();
654         let labels = self.fmt_successor_labels();
655         assert_eq!(successors.len(), labels.len());
656
657         match successors.len() {
658             0 => Ok(()),
659
660             1 => write!(fmt, " -> {:?}", successors[0]),
661
662             _ => {
663                 write!(fmt, " -> [")?;
664                 for (i, target) in successors.iter().enumerate() {
665                     if i > 0 {
666                         write!(fmt, ", ")?;
667                     }
668                     write!(fmt, "{}: {:?}", labels[i], target)?;
669                 }
670                 write!(fmt, "]")
671             }
672
673         }
674     }
675 }
676
677 impl<'tcx> TerminatorKind<'tcx> {
678     /// Write the "head" part of the terminator; that is, its name and the data it uses to pick the
679     /// successor basic block, if any. The only information not inlcuded is the list of possible
680     /// successors, which may be rendered differently between the text and the graphviz format.
681     pub fn fmt_head<W: Write>(&self, fmt: &mut W) -> fmt::Result {
682         use self::TerminatorKind::*;
683         match *self {
684             Goto { .. } => write!(fmt, "goto"),
685             SwitchInt { discr: ref lv, .. } => write!(fmt, "switchInt({:?})", lv),
686             Return => write!(fmt, "return"),
687             Resume => write!(fmt, "resume"),
688             Unreachable => write!(fmt, "unreachable"),
689             Drop { ref location, .. } => write!(fmt, "drop({:?})", location),
690             DropAndReplace { ref location, ref value, .. } =>
691                 write!(fmt, "replace({:?} <- {:?})", location, value),
692             Call { ref func, ref args, ref destination, .. } => {
693                 if let Some((ref destination, _)) = *destination {
694                     write!(fmt, "{:?} = ", destination)?;
695                 }
696                 write!(fmt, "{:?}(", func)?;
697                 for (index, arg) in args.iter().enumerate() {
698                     if index > 0 {
699                         write!(fmt, ", ")?;
700                     }
701                     write!(fmt, "{:?}", arg)?;
702                 }
703                 write!(fmt, ")")
704             }
705             Assert { ref cond, expected, ref msg, .. } => {
706                 write!(fmt, "assert(")?;
707                 if !expected {
708                     write!(fmt, "!")?;
709                 }
710                 write!(fmt, "{:?}, ", cond)?;
711
712                 match *msg {
713                     AssertMessage::BoundsCheck { ref len, ref index } => {
714                         write!(fmt, "{:?}, {:?}, {:?}",
715                                "index out of bounds: the len is {} but the index is {}",
716                                len, index)?;
717                     }
718                     AssertMessage::Math(ref err) => {
719                         write!(fmt, "{:?}", err.description())?;
720                     }
721                 }
722
723                 write!(fmt, ")")
724             }
725         }
726     }
727
728     /// Return the list of labels for the edges to the successor basic blocks.
729     pub fn fmt_successor_labels(&self) -> Vec<Cow<'static, str>> {
730         use self::TerminatorKind::*;
731         match *self {
732             Return | Resume | Unreachable => vec![],
733             Goto { .. } => vec!["".into()],
734             SwitchInt { ref values, .. } => {
735                 values.iter()
736                       .map(|const_val| {
737                           let mut buf = String::new();
738                           fmt_const_val(&mut buf, &ConstVal::Integral(*const_val)).unwrap();
739                           buf.into()
740                       })
741                       .chain(iter::once(String::from("otherwise").into()))
742                       .collect()
743             }
744             Call { destination: Some(_), cleanup: Some(_), .. } =>
745                 vec!["return".into_cow(), "unwind".into_cow()],
746             Call { destination: Some(_), cleanup: None, .. } => vec!["return".into_cow()],
747             Call { destination: None, cleanup: Some(_), .. } => vec!["unwind".into_cow()],
748             Call { destination: None, cleanup: None, .. } => vec![],
749             DropAndReplace { unwind: None, .. } |
750             Drop { unwind: None, .. } => vec!["return".into_cow()],
751             DropAndReplace { unwind: Some(_), .. } |
752             Drop { unwind: Some(_), .. } => {
753                 vec!["return".into_cow(), "unwind".into_cow()]
754             }
755             Assert { cleanup: None, .. } => vec!["".into()],
756             Assert { .. } =>
757                 vec!["success".into_cow(), "unwind".into_cow()]
758         }
759     }
760 }
761
762 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
763 pub enum AssertMessage<'tcx> {
764     BoundsCheck {
765         len: Operand<'tcx>,
766         index: Operand<'tcx>
767     },
768     Math(ConstMathErr)
769 }
770
771 ///////////////////////////////////////////////////////////////////////////
772 // Statements
773
774 #[derive(Clone, RustcEncodable, RustcDecodable)]
775 pub struct Statement<'tcx> {
776     pub source_info: SourceInfo,
777     pub kind: StatementKind<'tcx>,
778 }
779
780 impl<'tcx> Statement<'tcx> {
781     /// Changes a statement to a nop. This is both faster than deleting instructions and avoids
782     /// invalidating statement indices in `Location`s.
783     pub fn make_nop(&mut self) {
784         self.kind = StatementKind::Nop
785     }
786 }
787
788 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
789 pub enum StatementKind<'tcx> {
790     /// Write the RHS Rvalue to the LHS Lvalue.
791     Assign(Lvalue<'tcx>, Rvalue<'tcx>),
792
793     /// Write the discriminant for a variant to the enum Lvalue.
794     SetDiscriminant { lvalue: Lvalue<'tcx>, variant_index: usize },
795
796     /// Start a live range for the storage of the local.
797     StorageLive(Lvalue<'tcx>),
798
799     /// End the current live range for the storage of the local.
800     StorageDead(Lvalue<'tcx>),
801
802     InlineAsm {
803         asm: Box<InlineAsm>,
804         outputs: Vec<Lvalue<'tcx>>,
805         inputs: Vec<Operand<'tcx>>
806     },
807
808     /// Mark one terminating point of an extent (i.e. static region).
809     /// (The starting point(s) arise implicitly from borrows.)
810     EndRegion(CodeExtent),
811
812     /// No-op. Useful for deleting instructions without affecting statement indices.
813     Nop,
814 }
815
816 impl<'tcx> Debug for Statement<'tcx> {
817     fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
818         use self::StatementKind::*;
819         match self.kind {
820             Assign(ref lv, ref rv) => write!(fmt, "{:?} = {:?}", lv, rv),
821             // (reuse lifetime rendering policy from ppaux.)
822             EndRegion(ref ce) => write!(fmt, "EndRegion({})", ty::ReScope(*ce)),
823             StorageLive(ref lv) => write!(fmt, "StorageLive({:?})", lv),
824             StorageDead(ref lv) => write!(fmt, "StorageDead({:?})", lv),
825             SetDiscriminant{lvalue: ref lv, variant_index: index} => {
826                 write!(fmt, "discriminant({:?}) = {:?}", lv, index)
827             },
828             InlineAsm { ref asm, ref outputs, ref inputs } => {
829                 write!(fmt, "asm!({:?} : {:?} : {:?})", asm, outputs, inputs)
830             },
831             Nop => write!(fmt, "nop"),
832         }
833     }
834 }
835
836 ///////////////////////////////////////////////////////////////////////////
837 // Lvalues
838
839 /// A path to a value; something that can be evaluated without
840 /// changing or disturbing program state.
841 #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)]
842 pub enum Lvalue<'tcx> {
843     /// local variable
844     Local(Local),
845
846     /// static or static mut variable
847     Static(Box<Static<'tcx>>),
848
849     /// projection out of an lvalue (access a field, deref a pointer, etc)
850     Projection(Box<LvalueProjection<'tcx>>),
851 }
852
853 /// The def-id of a static, along with its normalized type (which is
854 /// stored to avoid requiring normalization when reading MIR).
855 #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)]
856 pub struct Static<'tcx> {
857     pub def_id: DefId,
858     pub ty: Ty<'tcx>,
859 }
860
861 impl_stable_hash_for!(struct Static<'tcx> {
862     def_id,
863     ty
864 });
865
866 /// The `Projection` data structure defines things of the form `B.x`
867 /// or `*B` or `B[index]`. Note that it is parameterized because it is
868 /// shared between `Constant` and `Lvalue`. See the aliases
869 /// `LvalueProjection` etc below.
870 #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
871 pub struct Projection<'tcx, B, V> {
872     pub base: B,
873     pub elem: ProjectionElem<'tcx, V>,
874 }
875
876 #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
877 pub enum ProjectionElem<'tcx, V> {
878     Deref,
879     Field(Field, Ty<'tcx>),
880     Index(V),
881
882     /// These indices are generated by slice patterns. Easiest to explain
883     /// by example:
884     ///
885     /// ```
886     /// [X, _, .._, _, _] => { offset: 0, min_length: 4, from_end: false },
887     /// [_, X, .._, _, _] => { offset: 1, min_length: 4, from_end: false },
888     /// [_, _, .._, X, _] => { offset: 2, min_length: 4, from_end: true },
889     /// [_, _, .._, _, X] => { offset: 1, min_length: 4, from_end: true },
890     /// ```
891     ConstantIndex {
892         /// index or -index (in Python terms), depending on from_end
893         offset: u32,
894         /// thing being indexed must be at least this long
895         min_length: u32,
896         /// counting backwards from end?
897         from_end: bool,
898     },
899
900     /// These indices are generated by slice patterns.
901     ///
902     /// slice[from:-to] in Python terms.
903     Subslice {
904         from: u32,
905         to: u32,
906     },
907
908     /// "Downcast" to a variant of an ADT. Currently, we only introduce
909     /// this for ADTs with more than one variant. It may be better to
910     /// just introduce it always, or always for enums.
911     Downcast(&'tcx AdtDef, usize),
912 }
913
914 /// Alias for projections as they appear in lvalues, where the base is an lvalue
915 /// and the index is an operand.
916 pub type LvalueProjection<'tcx> = Projection<'tcx, Lvalue<'tcx>, Operand<'tcx>>;
917
918 /// Alias for projections as they appear in lvalues, where the base is an lvalue
919 /// and the index is an operand.
920 pub type LvalueElem<'tcx> = ProjectionElem<'tcx, Operand<'tcx>>;
921
922 newtype_index!(Field, "field");
923
924 impl<'tcx> Lvalue<'tcx> {
925     pub fn field(self, f: Field, ty: Ty<'tcx>) -> Lvalue<'tcx> {
926         self.elem(ProjectionElem::Field(f, ty))
927     }
928
929     pub fn deref(self) -> Lvalue<'tcx> {
930         self.elem(ProjectionElem::Deref)
931     }
932
933     pub fn downcast(self, adt_def: &'tcx AdtDef, variant_index: usize) -> Lvalue<'tcx> {
934         self.elem(ProjectionElem::Downcast(adt_def, variant_index))
935     }
936
937     pub fn index(self, index: Operand<'tcx>) -> Lvalue<'tcx> {
938         self.elem(ProjectionElem::Index(index))
939     }
940
941     pub fn elem(self, elem: LvalueElem<'tcx>) -> Lvalue<'tcx> {
942         Lvalue::Projection(Box::new(LvalueProjection {
943             base: self,
944             elem,
945         }))
946     }
947 }
948
949 impl<'tcx> Debug for Lvalue<'tcx> {
950     fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
951         use self::Lvalue::*;
952
953         match *self {
954             Local(id) => write!(fmt, "{:?}", id),
955             Static(box self::Static { def_id, ty }) =>
956                 write!(fmt, "({}: {:?})", ty::tls::with(|tcx| tcx.item_path_str(def_id)), ty),
957             Projection(ref data) =>
958                 match data.elem {
959                     ProjectionElem::Downcast(ref adt_def, index) =>
960                         write!(fmt, "({:?} as {})", data.base, adt_def.variants[index].name),
961                     ProjectionElem::Deref =>
962                         write!(fmt, "(*{:?})", data.base),
963                     ProjectionElem::Field(field, ty) =>
964                         write!(fmt, "({:?}.{:?}: {:?})", data.base, field.index(), ty),
965                     ProjectionElem::Index(ref index) =>
966                         write!(fmt, "{:?}[{:?}]", data.base, index),
967                     ProjectionElem::ConstantIndex { offset, min_length, from_end: false } =>
968                         write!(fmt, "{:?}[{:?} of {:?}]", data.base, offset, min_length),
969                     ProjectionElem::ConstantIndex { offset, min_length, from_end: true } =>
970                         write!(fmt, "{:?}[-{:?} of {:?}]", data.base, offset, min_length),
971                     ProjectionElem::Subslice { from, to } if to == 0 =>
972                         write!(fmt, "{:?}[{:?}:]", data.base, from),
973                     ProjectionElem::Subslice { from, to } if from == 0 =>
974                         write!(fmt, "{:?}[:-{:?}]", data.base, to),
975                     ProjectionElem::Subslice { from, to } =>
976                         write!(fmt, "{:?}[{:?}:-{:?}]", data.base,
977                                from, to),
978
979                 },
980         }
981     }
982 }
983
984 ///////////////////////////////////////////////////////////////////////////
985 // Scopes
986
987 newtype_index!(VisibilityScope, "scope");
988 pub const ARGUMENT_VISIBILITY_SCOPE : VisibilityScope = VisibilityScope(0);
989
990 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
991 pub struct VisibilityScopeData {
992     pub span: Span,
993     pub parent_scope: Option<VisibilityScope>,
994 }
995
996 ///////////////////////////////////////////////////////////////////////////
997 // Operands
998
999 /// These are values that can appear inside an rvalue (or an index
1000 /// lvalue). They are intentionally limited to prevent rvalues from
1001 /// being nested in one another.
1002 #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)]
1003 pub enum Operand<'tcx> {
1004     Consume(Lvalue<'tcx>),
1005     Constant(Box<Constant<'tcx>>),
1006 }
1007
1008 impl<'tcx> Debug for Operand<'tcx> {
1009     fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
1010         use self::Operand::*;
1011         match *self {
1012             Constant(ref a) => write!(fmt, "{:?}", a),
1013             Consume(ref lv) => write!(fmt, "{:?}", lv),
1014         }
1015     }
1016 }
1017
1018 impl<'tcx> Operand<'tcx> {
1019     pub fn function_handle<'a>(
1020         tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
1021         def_id: DefId,
1022         substs: &'tcx Substs<'tcx>,
1023         span: Span,
1024     ) -> Self {
1025         Operand::Constant(box Constant {
1026             span,
1027             ty: tcx.type_of(def_id).subst(tcx, substs),
1028             literal: Literal::Value { value: ConstVal::Function(def_id, substs) },
1029         })
1030     }
1031
1032 }
1033
1034 ///////////////////////////////////////////////////////////////////////////
1035 /// Rvalues
1036
1037 #[derive(Clone, RustcEncodable, RustcDecodable)]
1038 pub enum Rvalue<'tcx> {
1039     /// x (either a move or copy, depending on type of x)
1040     Use(Operand<'tcx>),
1041
1042     /// [x; 32]
1043     Repeat(Operand<'tcx>, ConstUsize),
1044
1045     /// &x or &mut x
1046     Ref(Region<'tcx>, BorrowKind, Lvalue<'tcx>),
1047
1048     /// length of a [X] or [X;n] value
1049     Len(Lvalue<'tcx>),
1050
1051     Cast(CastKind, Operand<'tcx>, Ty<'tcx>),
1052
1053     BinaryOp(BinOp, Operand<'tcx>, Operand<'tcx>),
1054     CheckedBinaryOp(BinOp, Operand<'tcx>, Operand<'tcx>),
1055
1056     NullaryOp(NullOp, Ty<'tcx>),
1057     UnaryOp(UnOp, Operand<'tcx>),
1058
1059     /// Read the discriminant of an ADT.
1060     ///
1061     /// Undefined (i.e. no effort is made to make it defined, but there’s no reason why it cannot
1062     /// be defined to return, say, a 0) if ADT is not an enum.
1063     Discriminant(Lvalue<'tcx>),
1064
1065     /// Create an aggregate value, like a tuple or struct.  This is
1066     /// only needed because we want to distinguish `dest = Foo { x:
1067     /// ..., y: ... }` from `dest.x = ...; dest.y = ...;` in the case
1068     /// that `Foo` has a destructor. These rvalues can be optimized
1069     /// away after type-checking and before lowering.
1070     Aggregate(Box<AggregateKind<'tcx>>, Vec<Operand<'tcx>>),
1071 }
1072
1073 #[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
1074 pub enum CastKind {
1075     Misc,
1076
1077     /// Convert unique, zero-sized type for a fn to fn()
1078     ReifyFnPointer,
1079
1080     /// Convert non capturing closure to fn()
1081     ClosureFnPointer,
1082
1083     /// Convert safe fn() to unsafe fn()
1084     UnsafeFnPointer,
1085
1086     /// "Unsize" -- convert a thin-or-fat pointer to a fat pointer.
1087     /// trans must figure out the details once full monomorphization
1088     /// is known. For example, this could be used to cast from a
1089     /// `&[i32;N]` to a `&[i32]`, or a `Box<T>` to a `Box<Trait>`
1090     /// (presuming `T: Trait`).
1091     Unsize,
1092 }
1093
1094 #[derive(Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
1095 pub enum AggregateKind<'tcx> {
1096     /// The type is of the element
1097     Array(Ty<'tcx>),
1098     Tuple,
1099     /// The second field is variant number (discriminant), it's equal to 0
1100     /// for struct and union expressions. The fourth field is active field
1101     /// number and is present only for union expressions.
1102     Adt(&'tcx AdtDef, usize, &'tcx Substs<'tcx>, Option<usize>),
1103     Closure(DefId, ClosureSubsts<'tcx>),
1104 }
1105
1106 #[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
1107 pub enum BinOp {
1108     /// The `+` operator (addition)
1109     Add,
1110     /// The `-` operator (subtraction)
1111     Sub,
1112     /// The `*` operator (multiplication)
1113     Mul,
1114     /// The `/` operator (division)
1115     Div,
1116     /// The `%` operator (modulus)
1117     Rem,
1118     /// The `^` operator (bitwise xor)
1119     BitXor,
1120     /// The `&` operator (bitwise and)
1121     BitAnd,
1122     /// The `|` operator (bitwise or)
1123     BitOr,
1124     /// The `<<` operator (shift left)
1125     Shl,
1126     /// The `>>` operator (shift right)
1127     Shr,
1128     /// The `==` operator (equality)
1129     Eq,
1130     /// The `<` operator (less than)
1131     Lt,
1132     /// The `<=` operator (less than or equal to)
1133     Le,
1134     /// The `!=` operator (not equal to)
1135     Ne,
1136     /// The `>=` operator (greater than or equal to)
1137     Ge,
1138     /// The `>` operator (greater than)
1139     Gt,
1140     /// The `ptr.offset` operator
1141     Offset,
1142 }
1143
1144 impl BinOp {
1145     pub fn is_checkable(self) -> bool {
1146         use self::BinOp::*;
1147         match self {
1148             Add | Sub | Mul | Shl | Shr => true,
1149             _ => false
1150         }
1151     }
1152 }
1153
1154 #[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
1155 pub enum NullOp {
1156     /// Return the size of a value of that type
1157     SizeOf,
1158     /// Create a new uninitialized box for a value of that type
1159     Box,
1160 }
1161
1162 #[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
1163 pub enum UnOp {
1164     /// The `!` operator for logical inversion
1165     Not,
1166     /// The `-` operator for negation
1167     Neg,
1168 }
1169
1170 impl<'tcx> Debug for Rvalue<'tcx> {
1171     fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
1172         use self::Rvalue::*;
1173
1174         match *self {
1175             Use(ref lvalue) => write!(fmt, "{:?}", lvalue),
1176             Repeat(ref a, ref b) => write!(fmt, "[{:?}; {:?}]", a, b),
1177             Len(ref a) => write!(fmt, "Len({:?})", a),
1178             Cast(ref kind, ref lv, ref ty) => write!(fmt, "{:?} as {:?} ({:?})", lv, ty, kind),
1179             BinaryOp(ref op, ref a, ref b) => write!(fmt, "{:?}({:?}, {:?})", op, a, b),
1180             CheckedBinaryOp(ref op, ref a, ref b) => {
1181                 write!(fmt, "Checked{:?}({:?}, {:?})", op, a, b)
1182             }
1183             UnaryOp(ref op, ref a) => write!(fmt, "{:?}({:?})", op, a),
1184             Discriminant(ref lval) => write!(fmt, "discriminant({:?})", lval),
1185             NullaryOp(ref op, ref t) => write!(fmt, "{:?}({:?})", op, t),
1186             Ref(region, borrow_kind, ref lv) => {
1187                 let kind_str = match borrow_kind {
1188                     BorrowKind::Shared => "",
1189                     BorrowKind::Mut | BorrowKind::Unique => "mut ",
1190                 };
1191
1192                 // When identifying regions, add trailing space if
1193                 // necessary.
1194                 let region = if ppaux::identify_regions() {
1195                     let mut region = format!("{}", region);
1196                     if region.len() > 0 { region.push(' '); }
1197                     region
1198                 } else {
1199                     "".to_owned()
1200                 };
1201                 write!(fmt, "&{}{}{:?}", region, kind_str, lv)
1202             }
1203
1204             Aggregate(ref kind, ref lvs) => {
1205                 fn fmt_tuple(fmt: &mut Formatter, lvs: &[Operand]) -> fmt::Result {
1206                     let mut tuple_fmt = fmt.debug_tuple("");
1207                     for lv in lvs {
1208                         tuple_fmt.field(lv);
1209                     }
1210                     tuple_fmt.finish()
1211                 }
1212
1213                 match **kind {
1214                     AggregateKind::Array(_) => write!(fmt, "{:?}", lvs),
1215
1216                     AggregateKind::Tuple => {
1217                         match lvs.len() {
1218                             0 => write!(fmt, "()"),
1219                             1 => write!(fmt, "({:?},)", lvs[0]),
1220                             _ => fmt_tuple(fmt, lvs),
1221                         }
1222                     }
1223
1224                     AggregateKind::Adt(adt_def, variant, substs, _) => {
1225                         let variant_def = &adt_def.variants[variant];
1226
1227                         ppaux::parameterized(fmt, substs, variant_def.did, &[])?;
1228
1229                         match variant_def.ctor_kind {
1230                             CtorKind::Const => Ok(()),
1231                             CtorKind::Fn => fmt_tuple(fmt, lvs),
1232                             CtorKind::Fictive => {
1233                                 let mut struct_fmt = fmt.debug_struct("");
1234                                 for (field, lv) in variant_def.fields.iter().zip(lvs) {
1235                                     struct_fmt.field(&field.name.as_str(), lv);
1236                                 }
1237                                 struct_fmt.finish()
1238                             }
1239                         }
1240                     }
1241
1242                     AggregateKind::Closure(def_id, _) => ty::tls::with(|tcx| {
1243                         if let Some(node_id) = tcx.hir.as_local_node_id(def_id) {
1244                             let name = if tcx.sess.opts.debugging_opts.span_free_formats {
1245                                 format!("[closure@{:?}]", node_id)
1246                             } else {
1247                                 format!("[closure@{:?}]", tcx.hir.span(node_id))
1248                             };
1249                             let mut struct_fmt = fmt.debug_struct(&name);
1250
1251                             tcx.with_freevars(node_id, |freevars| {
1252                                 for (freevar, lv) in freevars.iter().zip(lvs) {
1253                                     let def_id = freevar.def.def_id();
1254                                     let var_id = tcx.hir.as_local_node_id(def_id).unwrap();
1255                                     let var_name = tcx.local_var_name_str(var_id);
1256                                     struct_fmt.field(&var_name, lv);
1257                                 }
1258                             });
1259
1260                             struct_fmt.finish()
1261                         } else {
1262                             write!(fmt, "[closure]")
1263                         }
1264                     }),
1265                 }
1266             }
1267         }
1268     }
1269 }
1270
1271 ///////////////////////////////////////////////////////////////////////////
1272 /// Constants
1273 ///
1274 /// Two constants are equal if they are the same constant. Note that
1275 /// this does not necessarily mean that they are "==" in Rust -- in
1276 /// particular one must be wary of `NaN`!
1277
1278 #[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
1279 pub struct Constant<'tcx> {
1280     pub span: Span,
1281     pub ty: Ty<'tcx>,
1282     pub literal: Literal<'tcx>,
1283 }
1284
1285 newtype_index!(Promoted, "promoted");
1286
1287 #[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
1288 pub enum Literal<'tcx> {
1289     Item {
1290         def_id: DefId,
1291         substs: &'tcx Substs<'tcx>,
1292     },
1293     Value {
1294         value: ConstVal<'tcx>,
1295     },
1296     Promoted {
1297         // Index into the `promoted` vector of `Mir`.
1298         index: Promoted
1299     },
1300 }
1301
1302 impl<'tcx> Debug for Constant<'tcx> {
1303     fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
1304         write!(fmt, "{:?}", self.literal)
1305     }
1306 }
1307
1308 impl<'tcx> Debug for Literal<'tcx> {
1309     fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
1310         use self::Literal::*;
1311         match *self {
1312             Item { def_id, substs } => {
1313                 ppaux::parameterized(fmt, substs, def_id, &[])
1314             }
1315             Value { ref value } => {
1316                 write!(fmt, "const ")?;
1317                 fmt_const_val(fmt, value)
1318             }
1319             Promoted { index } => {
1320                 write!(fmt, "{:?}", index)
1321             }
1322         }
1323     }
1324 }
1325
1326 /// Write a `ConstVal` in a way closer to the original source code than the `Debug` output.
1327 fn fmt_const_val<W: Write>(fmt: &mut W, const_val: &ConstVal) -> fmt::Result {
1328     use middle::const_val::ConstVal::*;
1329     match *const_val {
1330         Float(f) => write!(fmt, "{:?}", f),
1331         Integral(n) => write!(fmt, "{}", n),
1332         Str(ref s) => write!(fmt, "{:?}", s),
1333         ByteStr(ref bytes) => {
1334             let escaped: String = bytes
1335                 .iter()
1336                 .flat_map(|&ch| ascii::escape_default(ch).map(|c| c as char))
1337                 .collect();
1338             write!(fmt, "b\"{}\"", escaped)
1339         }
1340         Bool(b) => write!(fmt, "{:?}", b),
1341         Char(c) => write!(fmt, "{:?}", c),
1342         Variant(def_id) |
1343         Function(def_id, _) => write!(fmt, "{}", item_path_str(def_id)),
1344         Struct(_) | Tuple(_) | Array(_) | Repeat(..) =>
1345             bug!("ConstVal `{:?}` should not be in MIR", const_val),
1346     }
1347 }
1348
1349 fn item_path_str(def_id: DefId) -> String {
1350     ty::tls::with(|tcx| tcx.item_path_str(def_id))
1351 }
1352
1353 impl<'tcx> ControlFlowGraph for Mir<'tcx> {
1354
1355     type Node = BasicBlock;
1356
1357     fn num_nodes(&self) -> usize { self.basic_blocks.len() }
1358
1359     fn start_node(&self) -> Self::Node { START_BLOCK }
1360
1361     fn predecessors<'graph>(&'graph self, node: Self::Node)
1362                             -> <Self as GraphPredecessors<'graph>>::Iter
1363     {
1364         self.predecessors_for(node).clone().into_iter()
1365     }
1366     fn successors<'graph>(&'graph self, node: Self::Node)
1367                           -> <Self as GraphSuccessors<'graph>>::Iter
1368     {
1369         self.basic_blocks[node].terminator().successors().into_owned().into_iter()
1370     }
1371 }
1372
1373 impl<'a, 'b> GraphPredecessors<'b> for Mir<'a> {
1374     type Item = BasicBlock;
1375     type Iter = IntoIter<BasicBlock>;
1376 }
1377
1378 impl<'a, 'b>  GraphSuccessors<'b> for Mir<'a> {
1379     type Item = BasicBlock;
1380     type Iter = IntoIter<BasicBlock>;
1381 }
1382
1383 #[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
1384 pub struct Location {
1385     /// the location is within this block
1386     pub block: BasicBlock,
1387
1388     /// the location is the start of the this statement; or, if `statement_index`
1389     /// == num-statements, then the start of the terminator.
1390     pub statement_index: usize,
1391 }
1392
1393 impl fmt::Debug for Location {
1394     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1395         write!(fmt, "{:?}[{}]", self.block, self.statement_index)
1396     }
1397 }
1398
1399 impl Location {
1400     pub fn dominates(&self, other: &Location, dominators: &Dominators<BasicBlock>) -> bool {
1401         if self.block == other.block {
1402             self.statement_index <= other.statement_index
1403         } else {
1404             dominators.is_dominated_by(other.block, self.block)
1405         }
1406     }
1407 }
1408
1409
1410 /*
1411  * TypeFoldable implementations for MIR types
1412  */
1413
1414 impl<'tcx> TypeFoldable<'tcx> for Mir<'tcx> {
1415     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
1416         Mir {
1417             basic_blocks: self.basic_blocks.fold_with(folder),
1418             visibility_scopes: self.visibility_scopes.clone(),
1419             promoted: self.promoted.fold_with(folder),
1420             return_ty: self.return_ty.fold_with(folder),
1421             local_decls: self.local_decls.fold_with(folder),
1422             arg_count: self.arg_count,
1423             upvar_decls: self.upvar_decls.clone(),
1424             spread_arg: self.spread_arg,
1425             span: self.span,
1426             cache: cache::Cache::new()
1427         }
1428     }
1429
1430     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
1431         self.basic_blocks.visit_with(visitor) ||
1432         self.promoted.visit_with(visitor)     ||
1433         self.return_ty.visit_with(visitor)    ||
1434         self.local_decls.visit_with(visitor)
1435     }
1436 }
1437
1438 impl<'tcx> TypeFoldable<'tcx> for LocalDecl<'tcx> {
1439     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
1440         LocalDecl {
1441             ty: self.ty.fold_with(folder),
1442             ..self.clone()
1443         }
1444     }
1445
1446     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
1447         self.ty.visit_with(visitor)
1448     }
1449 }
1450
1451 impl<'tcx> TypeFoldable<'tcx> for BasicBlockData<'tcx> {
1452     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
1453         BasicBlockData {
1454             statements: self.statements.fold_with(folder),
1455             terminator: self.terminator.fold_with(folder),
1456             is_cleanup: self.is_cleanup
1457         }
1458     }
1459
1460     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
1461         self.statements.visit_with(visitor) || self.terminator.visit_with(visitor)
1462     }
1463 }
1464
1465 impl<'tcx> TypeFoldable<'tcx> for Statement<'tcx> {
1466     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
1467         use mir::StatementKind::*;
1468
1469         let kind = match self.kind {
1470             Assign(ref lval, ref rval) => Assign(lval.fold_with(folder), rval.fold_with(folder)),
1471             SetDiscriminant { ref lvalue, variant_index } => SetDiscriminant {
1472                 lvalue: lvalue.fold_with(folder),
1473                 variant_index,
1474             },
1475             StorageLive(ref lval) => StorageLive(lval.fold_with(folder)),
1476             StorageDead(ref lval) => StorageDead(lval.fold_with(folder)),
1477             InlineAsm { ref asm, ref outputs, ref inputs } => InlineAsm {
1478                 asm: asm.clone(),
1479                 outputs: outputs.fold_with(folder),
1480                 inputs: inputs.fold_with(folder)
1481             },
1482
1483             // Note for future: If we want to expose the extents
1484             // during the fold, we need to either generalize EndRegion
1485             // to carry `[ty::Region]`, or extend the `TypeFolder`
1486             // trait with a `fn fold_extent`.
1487             EndRegion(ref extent) => EndRegion(extent.clone()),
1488
1489             Nop => Nop,
1490         };
1491         Statement {
1492             source_info: self.source_info,
1493             kind,
1494         }
1495     }
1496
1497     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
1498         use mir::StatementKind::*;
1499
1500         match self.kind {
1501             Assign(ref lval, ref rval) => { lval.visit_with(visitor) || rval.visit_with(visitor) }
1502             SetDiscriminant { ref lvalue, .. } |
1503             StorageLive(ref lvalue) |
1504             StorageDead(ref lvalue) => lvalue.visit_with(visitor),
1505             InlineAsm { ref outputs, ref inputs, .. } =>
1506                 outputs.visit_with(visitor) || inputs.visit_with(visitor),
1507
1508             // Note for future: If we want to expose the extents
1509             // during the visit, we need to either generalize EndRegion
1510             // to carry `[ty::Region]`, or extend the `TypeVisitor`
1511             // trait with a `fn visit_extent`.
1512             EndRegion(ref _extent) => false,
1513
1514             Nop => false,
1515         }
1516     }
1517 }
1518
1519 impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
1520     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
1521         use mir::TerminatorKind::*;
1522
1523         let kind = match self.kind {
1524             Goto { target } => Goto { target: target },
1525             SwitchInt { ref discr, switch_ty, ref values, ref targets } => SwitchInt {
1526                 discr: discr.fold_with(folder),
1527                 switch_ty: switch_ty.fold_with(folder),
1528                 values: values.clone(),
1529                 targets: targets.clone()
1530             },
1531             Drop { ref location, target, unwind } => Drop {
1532                 location: location.fold_with(folder),
1533                 target,
1534                 unwind,
1535             },
1536             DropAndReplace { ref location, ref value, target, unwind } => DropAndReplace {
1537                 location: location.fold_with(folder),
1538                 value: value.fold_with(folder),
1539                 target,
1540                 unwind,
1541             },
1542             Call { ref func, ref args, ref destination, cleanup } => {
1543                 let dest = destination.as_ref().map(|&(ref loc, dest)| {
1544                     (loc.fold_with(folder), dest)
1545                 });
1546
1547                 Call {
1548                     func: func.fold_with(folder),
1549                     args: args.fold_with(folder),
1550                     destination: dest,
1551                     cleanup,
1552                 }
1553             },
1554             Assert { ref cond, expected, ref msg, target, cleanup } => {
1555                 let msg = if let AssertMessage::BoundsCheck { ref len, ref index } = *msg {
1556                     AssertMessage::BoundsCheck {
1557                         len: len.fold_with(folder),
1558                         index: index.fold_with(folder),
1559                     }
1560                 } else {
1561                     msg.clone()
1562                 };
1563                 Assert {
1564                     cond: cond.fold_with(folder),
1565                     expected,
1566                     msg,
1567                     target,
1568                     cleanup,
1569                 }
1570             },
1571             Resume => Resume,
1572             Return => Return,
1573             Unreachable => Unreachable,
1574         };
1575         Terminator {
1576             source_info: self.source_info,
1577             kind,
1578         }
1579     }
1580
1581     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
1582         use mir::TerminatorKind::*;
1583
1584         match self.kind {
1585             SwitchInt { ref discr, switch_ty, .. } =>
1586                 discr.visit_with(visitor) || switch_ty.visit_with(visitor),
1587             Drop { ref location, ..} => location.visit_with(visitor),
1588             DropAndReplace { ref location, ref value, ..} =>
1589                 location.visit_with(visitor) || value.visit_with(visitor),
1590             Call { ref func, ref args, ref destination, .. } => {
1591                 let dest = if let Some((ref loc, _)) = *destination {
1592                     loc.visit_with(visitor)
1593                 } else { false };
1594                 dest || func.visit_with(visitor) || args.visit_with(visitor)
1595             },
1596             Assert { ref cond, ref msg, .. } => {
1597                 if cond.visit_with(visitor) {
1598                     if let AssertMessage::BoundsCheck { ref len, ref index } = *msg {
1599                         len.visit_with(visitor) || index.visit_with(visitor)
1600                     } else {
1601                         false
1602                     }
1603                 } else {
1604                     false
1605                 }
1606             },
1607             Goto { .. } |
1608             Resume |
1609             Return |
1610             Unreachable => false
1611         }
1612     }
1613 }
1614
1615 impl<'tcx> TypeFoldable<'tcx> for Lvalue<'tcx> {
1616     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
1617         match self {
1618             &Lvalue::Projection(ref p) => Lvalue::Projection(p.fold_with(folder)),
1619             _ => self.clone()
1620         }
1621     }
1622
1623     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
1624         if let &Lvalue::Projection(ref p) = self {
1625             p.visit_with(visitor)
1626         } else {
1627             false
1628         }
1629     }
1630 }
1631
1632 impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
1633     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
1634         use mir::Rvalue::*;
1635         match *self {
1636             Use(ref op) => Use(op.fold_with(folder)),
1637             Repeat(ref op, len) => Repeat(op.fold_with(folder), len),
1638             Ref(region, bk, ref lval) => Ref(region.fold_with(folder), bk, lval.fold_with(folder)),
1639             Len(ref lval) => Len(lval.fold_with(folder)),
1640             Cast(kind, ref op, ty) => Cast(kind, op.fold_with(folder), ty.fold_with(folder)),
1641             BinaryOp(op, ref rhs, ref lhs) =>
1642                 BinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder)),
1643             CheckedBinaryOp(op, ref rhs, ref lhs) =>
1644                 CheckedBinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder)),
1645             UnaryOp(op, ref val) => UnaryOp(op, val.fold_with(folder)),
1646             Discriminant(ref lval) => Discriminant(lval.fold_with(folder)),
1647             NullaryOp(op, ty) => NullaryOp(op, ty.fold_with(folder)),
1648             Aggregate(ref kind, ref fields) => {
1649                 let kind = box match **kind {
1650                     AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)),
1651                     AggregateKind::Tuple => AggregateKind::Tuple,
1652                     AggregateKind::Adt(def, v, substs, n) =>
1653                         AggregateKind::Adt(def, v, substs.fold_with(folder), n),
1654                     AggregateKind::Closure(id, substs) =>
1655                         AggregateKind::Closure(id, substs.fold_with(folder))
1656                 };
1657                 Aggregate(kind, fields.fold_with(folder))
1658             }
1659         }
1660     }
1661
1662     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
1663         use mir::Rvalue::*;
1664         match *self {
1665             Use(ref op) => op.visit_with(visitor),
1666             Repeat(ref op, _) => op.visit_with(visitor),
1667             Ref(region, _, ref lval) => region.visit_with(visitor) || lval.visit_with(visitor),
1668             Len(ref lval) => lval.visit_with(visitor),
1669             Cast(_, ref op, ty) => op.visit_with(visitor) || ty.visit_with(visitor),
1670             BinaryOp(_, ref rhs, ref lhs) |
1671             CheckedBinaryOp(_, ref rhs, ref lhs) =>
1672                 rhs.visit_with(visitor) || lhs.visit_with(visitor),
1673             UnaryOp(_, ref val) => val.visit_with(visitor),
1674             Discriminant(ref lval) => lval.visit_with(visitor),
1675             NullaryOp(_, ty) => ty.visit_with(visitor),
1676             Aggregate(ref kind, ref fields) => {
1677                 (match **kind {
1678                     AggregateKind::Array(ty) => ty.visit_with(visitor),
1679                     AggregateKind::Tuple => false,
1680                     AggregateKind::Adt(_, _, substs, _) => substs.visit_with(visitor),
1681                     AggregateKind::Closure(_, substs) => substs.visit_with(visitor)
1682                 }) || fields.visit_with(visitor)
1683             }
1684         }
1685     }
1686 }
1687
1688 impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> {
1689     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
1690         match *self {
1691             Operand::Consume(ref lval) => Operand::Consume(lval.fold_with(folder)),
1692             Operand::Constant(ref c) => Operand::Constant(c.fold_with(folder)),
1693         }
1694     }
1695
1696     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
1697         match *self {
1698             Operand::Consume(ref lval) => lval.visit_with(visitor),
1699             Operand::Constant(ref c) => c.visit_with(visitor)
1700         }
1701     }
1702 }
1703
1704 impl<'tcx, B, V> TypeFoldable<'tcx> for Projection<'tcx, B, V>
1705     where B: TypeFoldable<'tcx>, V: TypeFoldable<'tcx>
1706 {
1707     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
1708         use mir::ProjectionElem::*;
1709
1710         let base = self.base.fold_with(folder);
1711         let elem = match self.elem {
1712             Deref => Deref,
1713             Field(f, ty) => Field(f, ty.fold_with(folder)),
1714             Index(ref v) => Index(v.fold_with(folder)),
1715             ref elem => elem.clone()
1716         };
1717
1718         Projection {
1719             base,
1720             elem,
1721         }
1722     }
1723
1724     fn super_visit_with<Vs: TypeVisitor<'tcx>>(&self, visitor: &mut Vs) -> bool {
1725         use mir::ProjectionElem::*;
1726
1727         self.base.visit_with(visitor) ||
1728             match self.elem {
1729                 Field(_, ty) => ty.visit_with(visitor),
1730                 Index(ref v) => v.visit_with(visitor),
1731                 _ => false
1732             }
1733     }
1734 }
1735
1736 impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> {
1737     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
1738         Constant {
1739             span: self.span.clone(),
1740             ty: self.ty.fold_with(folder),
1741             literal: self.literal.fold_with(folder)
1742         }
1743     }
1744     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
1745         self.ty.visit_with(visitor) || self.literal.visit_with(visitor)
1746     }
1747 }
1748
1749 impl<'tcx> TypeFoldable<'tcx> for Literal<'tcx> {
1750     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
1751         match *self {
1752             Literal::Item { def_id, substs } => Literal::Item {
1753                 def_id,
1754                 substs: substs.fold_with(folder)
1755             },
1756             _ => self.clone()
1757         }
1758     }
1759     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
1760         match *self {
1761             Literal::Item { substs, .. } => substs.visit_with(visitor),
1762             _ => false
1763         }
1764     }
1765 }