]> git.lizzy.rs Git - rust.git/blob - src/librustc/mir/mod.rs
Use assert_eq! in copy_from_slice
[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 [rustc guide] for more info.
12 //!
13 //! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir.html
14
15 use graphviz::IntoCow;
16 use hir::def::CtorKind;
17 use hir::def_id::DefId;
18 use hir::{self, InlineAsm};
19 use middle::region;
20 use mir::interpret::{EvalErrorKind, Scalar, Value};
21 use mir::visit::MirVisitable;
22 use rustc_apfloat::ieee::{Double, Single};
23 use rustc_apfloat::Float;
24 use rustc_data_structures::control_flow_graph::dominators::{dominators, Dominators};
25 use rustc_data_structures::control_flow_graph::ControlFlowGraph;
26 use rustc_data_structures::control_flow_graph::{GraphPredecessors, GraphSuccessors};
27 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
28 use rustc_data_structures::small_vec::SmallVec;
29 use rustc_data_structures::sync::Lrc;
30 use rustc_data_structures::sync::ReadGuard;
31 use rustc_serialize as serialize;
32 use std::borrow::Cow;
33 use std::fmt::{self, Debug, Formatter, Write};
34 use std::ops::{Index, IndexMut};
35 use std::slice;
36 use std::vec::IntoIter;
37 use std::{iter, mem, option, u32};
38 use syntax::ast::{self, Name};
39 use syntax::symbol::InternedString;
40 use syntax_pos::{Span, DUMMY_SP};
41 use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
42 use ty::subst::{Subst, Substs};
43 use ty::{self, AdtDef, CanonicalTy, ClosureSubsts, GeneratorSubsts, Region, Ty, TyCtxt};
44 use util::ppaux;
45
46 pub use mir::interpret::AssertMessage;
47
48 mod cache;
49 pub mod interpret;
50 pub mod mono;
51 pub mod tcx;
52 pub mod traversal;
53 pub mod visit;
54
55 /// Types for locals
56 type LocalDecls<'tcx> = IndexVec<Local, LocalDecl<'tcx>>;
57
58 pub trait HasLocalDecls<'tcx> {
59     fn local_decls(&self) -> &LocalDecls<'tcx>;
60 }
61
62 impl<'tcx> HasLocalDecls<'tcx> for LocalDecls<'tcx> {
63     fn local_decls(&self) -> &LocalDecls<'tcx> {
64         self
65     }
66 }
67
68 impl<'tcx> HasLocalDecls<'tcx> for Mir<'tcx> {
69     fn local_decls(&self) -> &LocalDecls<'tcx> {
70         &self.local_decls
71     }
72 }
73
74 /// Lowered representation of a single function.
75 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
76 pub struct Mir<'tcx> {
77     /// List of basic blocks. References to basic block use a newtyped index type `BasicBlock`
78     /// that indexes into this vector.
79     basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
80
81     /// List of source scopes; these are referenced by statements
82     /// and used for debuginfo. Indexed by a `SourceScope`.
83     pub source_scopes: IndexVec<SourceScope, SourceScopeData>,
84
85     /// Crate-local information for each source scope, that can't (and
86     /// needn't) be tracked across crates.
87     pub source_scope_local_data: ClearCrossCrate<IndexVec<SourceScope, SourceScopeLocalData>>,
88
89     /// Rvalues promoted from this function, such as borrows of constants.
90     /// Each of them is the Mir of a constant with the fn's type parameters
91     /// in scope, but a separate set of locals.
92     pub promoted: IndexVec<Promoted, Mir<'tcx>>,
93
94     /// Yield type of the function, if it is a generator.
95     pub yield_ty: Option<Ty<'tcx>>,
96
97     /// Generator drop glue
98     pub generator_drop: Option<Box<Mir<'tcx>>>,
99
100     /// The layout of a generator. Produced by the state transformation.
101     pub generator_layout: Option<GeneratorLayout<'tcx>>,
102
103     /// Declarations of locals.
104     ///
105     /// The first local is the return value pointer, followed by `arg_count`
106     /// locals for the function arguments, followed by any user-declared
107     /// variables and temporaries.
108     pub local_decls: LocalDecls<'tcx>,
109
110     /// Number of arguments this function takes.
111     ///
112     /// Starting at local 1, `arg_count` locals will be provided by the caller
113     /// and can be assumed to be initialized.
114     ///
115     /// If this MIR was built for a constant, this will be 0.
116     pub arg_count: usize,
117
118     /// Names and capture modes of all the closure upvars, assuming
119     /// the first argument is either the closure or a reference to it.
120     pub upvar_decls: Vec<UpvarDecl>,
121
122     /// Mark an argument local (which must be a tuple) as getting passed as
123     /// its individual components at the LLVM level.
124     ///
125     /// This is used for the "rust-call" ABI.
126     pub spread_arg: Option<Local>,
127
128     /// A span representing this MIR, for error reporting
129     pub span: Span,
130
131     /// A cache for various calculations
132     cache: cache::Cache,
133 }
134
135 /// where execution begins
136 pub const START_BLOCK: BasicBlock = BasicBlock(0);
137
138 impl<'tcx> Mir<'tcx> {
139     pub fn new(
140         basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
141         source_scopes: IndexVec<SourceScope, SourceScopeData>,
142         source_scope_local_data: ClearCrossCrate<IndexVec<SourceScope, SourceScopeLocalData>>,
143         promoted: IndexVec<Promoted, Mir<'tcx>>,
144         yield_ty: Option<Ty<'tcx>>,
145         local_decls: IndexVec<Local, LocalDecl<'tcx>>,
146         arg_count: usize,
147         upvar_decls: Vec<UpvarDecl>,
148         span: Span,
149     ) -> Self {
150         // We need `arg_count` locals, and one for the return place
151         assert!(
152             local_decls.len() >= arg_count + 1,
153             "expected at least {} locals, got {}",
154             arg_count + 1,
155             local_decls.len()
156         );
157
158         Mir {
159             basic_blocks,
160             source_scopes,
161             source_scope_local_data,
162             promoted,
163             yield_ty,
164             generator_drop: None,
165             generator_layout: None,
166             local_decls,
167             arg_count,
168             upvar_decls,
169             spread_arg: None,
170             span,
171             cache: cache::Cache::new(),
172         }
173     }
174
175     #[inline]
176     pub fn basic_blocks(&self) -> &IndexVec<BasicBlock, BasicBlockData<'tcx>> {
177         &self.basic_blocks
178     }
179
180     #[inline]
181     pub fn basic_blocks_mut(&mut self) -> &mut IndexVec<BasicBlock, BasicBlockData<'tcx>> {
182         self.cache.invalidate();
183         &mut self.basic_blocks
184     }
185
186     #[inline]
187     pub fn basic_blocks_and_local_decls_mut(
188         &mut self,
189     ) -> (
190         &mut IndexVec<BasicBlock, BasicBlockData<'tcx>>,
191         &mut LocalDecls<'tcx>,
192     ) {
193         self.cache.invalidate();
194         (&mut self.basic_blocks, &mut self.local_decls)
195     }
196
197     #[inline]
198     pub fn predecessors(&self) -> ReadGuard<IndexVec<BasicBlock, Vec<BasicBlock>>> {
199         self.cache.predecessors(self)
200     }
201
202     #[inline]
203     pub fn predecessors_for(&self, bb: BasicBlock) -> ReadGuard<Vec<BasicBlock>> {
204         ReadGuard::map(self.predecessors(), |p| &p[bb])
205     }
206
207     #[inline]
208     pub fn dominators(&self) -> Dominators<BasicBlock> {
209         dominators(self)
210     }
211
212     #[inline]
213     pub fn local_kind(&self, local: Local) -> LocalKind {
214         let index = local.0 as usize;
215         if index == 0 {
216             debug_assert!(
217                 self.local_decls[local].mutability == Mutability::Mut,
218                 "return place should be mutable"
219             );
220
221             LocalKind::ReturnPointer
222         } else if index < self.arg_count + 1 {
223             LocalKind::Arg
224         } else if self.local_decls[local].name.is_some() {
225             LocalKind::Var
226         } else {
227             debug_assert!(
228                 self.local_decls[local].mutability == Mutability::Mut,
229                 "temp should be mutable"
230             );
231
232             LocalKind::Temp
233         }
234     }
235
236     /// Returns an iterator over all temporaries.
237     #[inline]
238     pub fn temps_iter<'a>(&'a self) -> impl Iterator<Item = Local> + 'a {
239         (self.arg_count + 1..self.local_decls.len()).filter_map(move |index| {
240             let local = Local::new(index);
241             if self.local_decls[local].is_user_variable.is_some() {
242                 None
243             } else {
244                 Some(local)
245             }
246         })
247     }
248
249     /// Returns an iterator over all user-declared locals.
250     #[inline]
251     pub fn vars_iter<'a>(&'a self) -> impl Iterator<Item = Local> + 'a {
252         (self.arg_count + 1..self.local_decls.len()).filter_map(move |index| {
253             let local = Local::new(index);
254             if self.local_decls[local].is_user_variable.is_some() {
255                 Some(local)
256             } else {
257                 None
258             }
259         })
260     }
261
262     /// Returns an iterator over all user-declared mutable arguments and locals.
263     #[inline]
264     pub fn mut_vars_and_args_iter<'a>(&'a self) -> impl Iterator<Item = Local> + 'a {
265         (1..self.local_decls.len()).filter_map(move |index| {
266             let local = Local::new(index);
267             let decl = &self.local_decls[local];
268             if (decl.is_user_variable.is_some() || index < self.arg_count + 1)
269                 && decl.mutability == Mutability::Mut
270             {
271                 Some(local)
272             } else {
273                 None
274             }
275         })
276     }
277
278     /// Returns an iterator over all function arguments.
279     #[inline]
280     pub fn args_iter(&self) -> impl Iterator<Item = Local> {
281         let arg_count = self.arg_count;
282         (1..arg_count + 1).map(Local::new)
283     }
284
285     /// Returns an iterator over all user-defined variables and compiler-generated temporaries (all
286     /// locals that are neither arguments nor the return place).
287     #[inline]
288     pub fn vars_and_temps_iter(&self) -> impl Iterator<Item = Local> {
289         let arg_count = self.arg_count;
290         let local_count = self.local_decls.len();
291         (arg_count + 1..local_count).map(Local::new)
292     }
293
294     /// Changes a statement to a nop. This is both faster than deleting instructions and avoids
295     /// invalidating statement indices in `Location`s.
296     pub fn make_statement_nop(&mut self, location: Location) {
297         let block = &mut self[location.block];
298         debug_assert!(location.statement_index < block.statements.len());
299         block.statements[location.statement_index].make_nop()
300     }
301
302     /// Returns the source info associated with `location`.
303     pub fn source_info(&self, location: Location) -> &SourceInfo {
304         let block = &self[location.block];
305         let stmts = &block.statements;
306         let idx = location.statement_index;
307         if idx < stmts.len() {
308             &stmts[idx].source_info
309         } else {
310             assert!(idx == stmts.len());
311             &block.terminator().source_info
312         }
313     }
314
315     /// Check if `sub` is a sub scope of `sup`
316     pub fn is_sub_scope(&self, mut sub: SourceScope, sup: SourceScope) -> bool {
317         loop {
318             if sub == sup {
319                 return true;
320             }
321             match self.source_scopes[sub].parent_scope {
322                 None => return false,
323                 Some(p) => sub = p,
324             }
325         }
326     }
327
328     /// Return the return type, it always return first element from `local_decls` array
329     pub fn return_ty(&self) -> Ty<'tcx> {
330         self.local_decls[RETURN_PLACE].ty
331     }
332 }
333
334 #[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
335 pub enum Safety {
336     Safe,
337     /// Unsafe because of a PushUnsafeBlock
338     BuiltinUnsafe,
339     /// Unsafe because of an unsafe fn
340     FnUnsafe,
341     /// Unsafe because of an `unsafe` block
342     ExplicitUnsafe(ast::NodeId),
343 }
344
345 impl_stable_hash_for!(struct Mir<'tcx> {
346     basic_blocks,
347     source_scopes,
348     source_scope_local_data,
349     promoted,
350     yield_ty,
351     generator_drop,
352     generator_layout,
353     local_decls,
354     arg_count,
355     upvar_decls,
356     spread_arg,
357     span,
358     cache
359 });
360
361 impl<'tcx> Index<BasicBlock> for Mir<'tcx> {
362     type Output = BasicBlockData<'tcx>;
363
364     #[inline]
365     fn index(&self, index: BasicBlock) -> &BasicBlockData<'tcx> {
366         &self.basic_blocks()[index]
367     }
368 }
369
370 impl<'tcx> IndexMut<BasicBlock> for Mir<'tcx> {
371     #[inline]
372     fn index_mut(&mut self, index: BasicBlock) -> &mut BasicBlockData<'tcx> {
373         &mut self.basic_blocks_mut()[index]
374     }
375 }
376
377 #[derive(Copy, Clone, Debug)]
378 pub enum ClearCrossCrate<T> {
379     Clear,
380     Set(T),
381 }
382
383 impl<T: serialize::Encodable> serialize::UseSpecializedEncodable for ClearCrossCrate<T> {}
384 impl<T: serialize::Decodable> serialize::UseSpecializedDecodable for ClearCrossCrate<T> {}
385
386 /// Grouped information about the source code origin of a MIR entity.
387 /// Intended to be inspected by diagnostics and debuginfo.
388 /// Most passes can work with it as a whole, within a single function.
389 #[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
390 pub struct SourceInfo {
391     /// Source span for the AST pertaining to this MIR entity.
392     pub span: Span,
393
394     /// The source scope, keeping track of which bindings can be
395     /// seen by debuginfo, active lint levels, `unsafe {...}`, etc.
396     pub scope: SourceScope,
397 }
398
399 ///////////////////////////////////////////////////////////////////////////
400 // Mutability and borrow kinds
401
402 #[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
403 pub enum Mutability {
404     Mut,
405     Not,
406 }
407
408 impl From<Mutability> for hir::Mutability {
409     fn from(m: Mutability) -> Self {
410         match m {
411             Mutability::Mut => hir::MutMutable,
412             Mutability::Not => hir::MutImmutable,
413         }
414     }
415 }
416
417 #[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
418 pub enum BorrowKind {
419     /// Data must be immutable and is aliasable.
420     Shared,
421
422     /// Data must be immutable but not aliasable.  This kind of borrow
423     /// cannot currently be expressed by the user and is used only in
424     /// implicit closure bindings. It is needed when you the closure
425     /// is borrowing or mutating a mutable referent, e.g.:
426     ///
427     ///    let x: &mut isize = ...;
428     ///    let y = || *x += 5;
429     ///
430     /// If we were to try to translate this closure into a more explicit
431     /// form, we'd encounter an error with the code as written:
432     ///
433     ///    struct Env { x: & &mut isize }
434     ///    let x: &mut isize = ...;
435     ///    let y = (&mut Env { &x }, fn_ptr);  // Closure is pair of env and fn
436     ///    fn fn_ptr(env: &mut Env) { **env.x += 5; }
437     ///
438     /// This is then illegal because you cannot mutate a `&mut` found
439     /// in an aliasable location. To solve, you'd have to translate with
440     /// an `&mut` borrow:
441     ///
442     ///    struct Env { x: & &mut isize }
443     ///    let x: &mut isize = ...;
444     ///    let y = (&mut Env { &mut x }, fn_ptr); // changed from &x to &mut x
445     ///    fn fn_ptr(env: &mut Env) { **env.x += 5; }
446     ///
447     /// Now the assignment to `**env.x` is legal, but creating a
448     /// mutable pointer to `x` is not because `x` is not mutable. We
449     /// could fix this by declaring `x` as `let mut x`. This is ok in
450     /// user code, if awkward, but extra weird for closures, since the
451     /// borrow is hidden.
452     ///
453     /// So we introduce a "unique imm" borrow -- the referent is
454     /// immutable, but not aliasable. This solves the problem. For
455     /// simplicity, we don't give users the way to express this
456     /// borrow, it's just used when translating closures.
457     Unique,
458
459     /// Data is mutable and not aliasable.
460     Mut {
461         /// True if this borrow arose from method-call auto-ref
462         /// (i.e. `adjustment::Adjust::Borrow`)
463         allow_two_phase_borrow: bool,
464     },
465 }
466
467 impl BorrowKind {
468     pub fn allows_two_phase_borrow(&self) -> bool {
469         match *self {
470             BorrowKind::Shared | BorrowKind::Unique => false,
471             BorrowKind::Mut {
472                 allow_two_phase_borrow,
473             } => allow_two_phase_borrow,
474         }
475     }
476 }
477
478 ///////////////////////////////////////////////////////////////////////////
479 // Variables and temps
480
481 newtype_index!(Local
482     {
483         DEBUG_FORMAT = "_{}",
484         const RETURN_PLACE = 0,
485     });
486
487 /// Classifies locals into categories. See `Mir::local_kind`.
488 #[derive(PartialEq, Eq, Debug)]
489 pub enum LocalKind {
490     /// User-declared variable binding
491     Var,
492     /// Compiler-introduced temporary
493     Temp,
494     /// Function argument
495     Arg,
496     /// Location of function's return value
497     ReturnPointer,
498 }
499
500 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
501 pub struct VarBindingForm {
502     /// Is variable bound via `x`, `mut x`, `ref x`, or `ref mut x`?
503     pub binding_mode: ty::BindingMode,
504     /// If an explicit type was provided for this variable binding,
505     /// this holds the source Span of that type.
506     ///
507     /// NOTE: If you want to change this to a `HirId`, be wary that
508     /// doing so breaks incremental compilation (as of this writing),
509     /// while a `Span` does not cause our tests to fail.
510     pub opt_ty_info: Option<Span>,
511 }
512
513 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
514 pub enum BindingForm {
515     /// This is a binding for a non-`self` binding, or a `self` that has an explicit type.
516     Var(VarBindingForm),
517     /// Binding for a `self`/`&self`/`&mut self` binding where the type is implicit.
518     ImplicitSelf,
519 }
520
521 CloneTypeFoldableAndLiftImpls! { BindingForm, }
522
523 impl_stable_hash_for!(struct self::VarBindingForm { binding_mode, opt_ty_info });
524
525 impl_stable_hash_for!(enum self::BindingForm { Var(binding), ImplicitSelf, });
526
527 /// A MIR local.
528 ///
529 /// This can be a binding declared by the user, a temporary inserted by the compiler, a function
530 /// argument, or the return place.
531 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
532 pub struct LocalDecl<'tcx> {
533     /// `let mut x` vs `let x`.
534     ///
535     /// Temporaries and the return place are always mutable.
536     pub mutability: Mutability,
537
538     /// Some(binding_mode) if this corresponds to a user-declared local variable.
539     ///
540     /// This is solely used for local diagnostics when generating
541     /// warnings/errors when compiling the current crate, and
542     /// therefore it need not be visible across crates. pnkfelix
543     /// currently hypothesized we *need* to wrap this in a
544     /// `ClearCrossCrate` as long as it carries as `HirId`.
545     pub is_user_variable: Option<ClearCrossCrate<BindingForm>>,
546
547     /// True if this is an internal local
548     ///
549     /// These locals are not based on types in the source code and are only used
550     /// for a few desugarings at the moment.
551     ///
552     /// The generator transformation will sanity check the locals which are live
553     /// across a suspension point against the type components of the generator
554     /// which type checking knows are live across a suspension point. We need to
555     /// flag drop flags to avoid triggering this check as they are introduced
556     /// after typeck.
557     ///
558     /// Unsafety checking will also ignore dereferences of these locals,
559     /// so they can be used for raw pointers only used in a desugaring.
560     ///
561     /// This should be sound because the drop flags are fully algebraic, and
562     /// therefore don't affect the OIBIT or outlives properties of the
563     /// generator.
564     pub internal: bool,
565
566     /// Type of this local.
567     pub ty: Ty<'tcx>,
568
569     /// Name of the local, used in debuginfo and pretty-printing.
570     ///
571     /// Note that function arguments can also have this set to `Some(_)`
572     /// to generate better debuginfo.
573     pub name: Option<Name>,
574
575     /// The *syntactic* (i.e. not visibility) source scope the local is defined
576     /// in. If the local was defined in a let-statement, this
577     /// is *within* the let-statement, rather than outside
578     /// of it.
579     ///
580     /// This is needed because the visibility source scope of locals within
581     /// a let-statement is weird.
582     ///
583     /// The reason is that we want the local to be *within* the let-statement
584     /// for lint purposes, but we want the local to be *after* the let-statement
585     /// for names-in-scope purposes.
586     ///
587     /// That's it, if we have a let-statement like the one in this
588     /// function:
589     ///
590     /// ```
591     /// fn foo(x: &str) {
592     ///     #[allow(unused_mut)]
593     ///     let mut x: u32 = { // <- one unused mut
594     ///         let mut y: u32 = x.parse().unwrap();
595     ///         y + 2
596     ///     };
597     ///     drop(x);
598     /// }
599     /// ```
600     ///
601     /// Then, from a lint point of view, the declaration of `x: u32`
602     /// (and `y: u32`) are within the `#[allow(unused_mut)]` scope - the
603     /// lint scopes are the same as the AST/HIR nesting.
604     ///
605     /// However, from a name lookup point of view, the scopes look more like
606     /// as if the let-statements were `match` expressions:
607     ///
608     /// ```
609     /// fn foo(x: &str) {
610     ///     match {
611     ///         match x.parse().unwrap() {
612     ///             y => y + 2
613     ///         }
614     ///     } {
615     ///         x => drop(x)
616     ///     };
617     /// }
618     /// ```
619     ///
620     /// We care about the name-lookup scopes for debuginfo - if the
621     /// debuginfo instruction pointer is at the call to `x.parse()`, we
622     /// want `x` to refer to `x: &str`, but if it is at the call to
623     /// `drop(x)`, we want it to refer to `x: u32`.
624     ///
625     /// To allow both uses to work, we need to have more than a single scope
626     /// for a local. We have the `source_info.scope` represent the
627     /// "syntactic" lint scope (with a variable being under its let
628     /// block) while the `visibility_scope` represents the "local variable"
629     /// scope (where the "rest" of a block is under all prior let-statements).
630     ///
631     /// The end result looks like this:
632     ///
633     /// ```text
634     /// ROOT SCOPE
635     ///  │{ argument x: &str }
636     ///  │
637     ///  │ │{ #[allow(unused_mut] } // this is actually split into 2 scopes
638     ///  │ │                        // in practice because I'm lazy.
639     ///  │ │
640     ///  │ │← x.source_info.scope
641     ///  │ │← `x.parse().unwrap()`
642     ///  │ │
643     ///  │ │ │← y.source_info.scope
644     ///  │ │
645     ///  │ │ │{ let y: u32 }
646     ///  │ │ │
647     ///  │ │ │← y.visibility_scope
648     ///  │ │ │← `y + 2`
649     ///  │
650     ///  │ │{ let x: u32 }
651     ///  │ │← x.visibility_scope
652     ///  │ │← `drop(x)` // this accesses `x: u32`
653     /// ```
654     pub source_info: SourceInfo,
655
656     /// Source scope within which the local is visible (for debuginfo)
657     /// (see `source_info` for more details).
658     pub visibility_scope: SourceScope,
659 }
660
661 impl<'tcx> LocalDecl<'tcx> {
662     /// Returns true only if local is a binding that can itself be
663     /// made mutable via the addition of the `mut` keyword, namely
664     /// something like the occurrences of `x` in:
665     /// - `fn foo(x: Type) { ... }`,
666     /// - `let x = ...`,
667     /// - or `match ... { C(x) => ... }`
668     pub fn can_be_made_mutable(&self) -> bool {
669         match self.is_user_variable {
670             Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
671                 binding_mode: ty::BindingMode::BindByValue(_),
672                 opt_ty_info: _,
673             }))) => true,
674
675             // FIXME: might be able to thread the distinction between
676             // `self`/`mut self`/`&self`/`&mut self` into the
677             // `BindingForm::ImplicitSelf` variant, (and then return
678             // true here for solely the first case).
679             _ => false,
680         }
681     }
682
683     /// Returns true if local is definitely not a `ref ident` or
684     /// `ref mut ident` binding. (Such bindings cannot be made into
685     /// mutable bindings, but the inverse does not necessarily hold).
686     pub fn is_nonref_binding(&self) -> bool {
687         match self.is_user_variable {
688             Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
689                 binding_mode: ty::BindingMode::BindByValue(_),
690                 opt_ty_info: _,
691             }))) => true,
692
693             Some(ClearCrossCrate::Set(BindingForm::ImplicitSelf)) => true,
694
695             _ => false,
696         }
697     }
698
699     /// Create a new `LocalDecl` for a temporary.
700     #[inline]
701     pub fn new_temp(ty: Ty<'tcx>, span: Span) -> Self {
702         LocalDecl {
703             mutability: Mutability::Mut,
704             ty,
705             name: None,
706             source_info: SourceInfo {
707                 span,
708                 scope: OUTERMOST_SOURCE_SCOPE,
709             },
710             visibility_scope: OUTERMOST_SOURCE_SCOPE,
711             internal: false,
712             is_user_variable: None,
713         }
714     }
715
716     /// Create a new `LocalDecl` for a internal temporary.
717     #[inline]
718     pub fn new_internal(ty: Ty<'tcx>, span: Span) -> Self {
719         LocalDecl {
720             mutability: Mutability::Mut,
721             ty,
722             name: None,
723             source_info: SourceInfo {
724                 span,
725                 scope: OUTERMOST_SOURCE_SCOPE,
726             },
727             visibility_scope: OUTERMOST_SOURCE_SCOPE,
728             internal: true,
729             is_user_variable: None,
730         }
731     }
732
733     /// Builds a `LocalDecl` for the return place.
734     ///
735     /// This must be inserted into the `local_decls` list as the first local.
736     #[inline]
737     pub fn new_return_place(return_ty: Ty, span: Span) -> LocalDecl {
738         LocalDecl {
739             mutability: Mutability::Mut,
740             ty: return_ty,
741             source_info: SourceInfo {
742                 span,
743                 scope: OUTERMOST_SOURCE_SCOPE,
744             },
745             visibility_scope: OUTERMOST_SOURCE_SCOPE,
746             internal: false,
747             name: None, // FIXME maybe we do want some name here?
748             is_user_variable: None,
749         }
750     }
751 }
752
753 /// A closure capture, with its name and mode.
754 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
755 pub struct UpvarDecl {
756     pub debug_name: Name,
757
758     /// If true, the capture is behind a reference.
759     pub by_ref: bool,
760
761     pub mutability: Mutability,
762 }
763
764 ///////////////////////////////////////////////////////////////////////////
765 // BasicBlock
766
767 newtype_index!(BasicBlock { DEBUG_FORMAT = "bb{}" });
768
769 impl BasicBlock {
770     pub fn start_location(self) -> Location {
771         Location {
772             block: self,
773             statement_index: 0,
774         }
775     }
776 }
777
778 ///////////////////////////////////////////////////////////////////////////
779 // BasicBlockData and Terminator
780
781 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
782 pub struct BasicBlockData<'tcx> {
783     /// List of statements in this block.
784     pub statements: Vec<Statement<'tcx>>,
785
786     /// Terminator for this block.
787     ///
788     /// NB. This should generally ONLY be `None` during construction.
789     /// Therefore, you should generally access it via the
790     /// `terminator()` or `terminator_mut()` methods. The only
791     /// exception is that certain passes, such as `simplify_cfg`, swap
792     /// out the terminator temporarily with `None` while they continue
793     /// to recurse over the set of basic blocks.
794     pub terminator: Option<Terminator<'tcx>>,
795
796     /// If true, this block lies on an unwind path. This is used
797     /// during codegen where distinct kinds of basic blocks may be
798     /// generated (particularly for MSVC cleanup). Unwind blocks must
799     /// only branch to other unwind blocks.
800     pub is_cleanup: bool,
801 }
802
803 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
804 pub struct Terminator<'tcx> {
805     pub source_info: SourceInfo,
806     pub kind: TerminatorKind<'tcx>,
807 }
808
809 #[derive(Clone, RustcEncodable, RustcDecodable)]
810 pub enum TerminatorKind<'tcx> {
811     /// block should have one successor in the graph; we jump there
812     Goto { target: BasicBlock },
813
814     /// operand evaluates to an integer; jump depending on its value
815     /// to one of the targets, and otherwise fallback to `otherwise`
816     SwitchInt {
817         /// discriminant value being tested
818         discr: Operand<'tcx>,
819
820         /// type of value being tested
821         switch_ty: Ty<'tcx>,
822
823         /// Possible values. The locations to branch to in each case
824         /// are found in the corresponding indices from the `targets` vector.
825         values: Cow<'tcx, [u128]>,
826
827         /// Possible branch sites. The last element of this vector is used
828         /// for the otherwise branch, so targets.len() == values.len() + 1
829         /// should hold.
830         // This invariant is quite non-obvious and also could be improved.
831         // One way to make this invariant is to have something like this instead:
832         //
833         // branches: Vec<(ConstInt, BasicBlock)>,
834         // otherwise: Option<BasicBlock> // exhaustive if None
835         //
836         // However we’ve decided to keep this as-is until we figure a case
837         // where some other approach seems to be strictly better than other.
838         targets: Vec<BasicBlock>,
839     },
840
841     /// Indicates that the landing pad is finished and unwinding should
842     /// continue. Emitted by build::scope::diverge_cleanup.
843     Resume,
844
845     /// Indicates that the landing pad is finished and that the process
846     /// should abort. Used to prevent unwinding for foreign items.
847     Abort,
848
849     /// Indicates a normal return. The return place should have
850     /// been filled in by now. This should occur at most once.
851     Return,
852
853     /// Indicates a terminator that can never be reached.
854     Unreachable,
855
856     /// Drop the Place
857     Drop {
858         location: Place<'tcx>,
859         target: BasicBlock,
860         unwind: Option<BasicBlock>,
861     },
862
863     /// Drop the Place and assign the new value over it. This ensures
864     /// that the assignment to `P` occurs *even if* the destructor for
865     /// place unwinds. Its semantics are best explained by by the
866     /// elaboration:
867     ///
868     /// ```
869     /// BB0 {
870     ///   DropAndReplace(P <- V, goto BB1, unwind BB2)
871     /// }
872     /// ```
873     ///
874     /// becomes
875     ///
876     /// ```
877     /// BB0 {
878     ///   Drop(P, goto BB1, unwind BB2)
879     /// }
880     /// BB1 {
881     ///   // P is now unitialized
882     ///   P <- V
883     /// }
884     /// BB2 {
885     ///   // P is now unitialized -- its dtor panicked
886     ///   P <- V
887     /// }
888     /// ```
889     DropAndReplace {
890         location: Place<'tcx>,
891         value: Operand<'tcx>,
892         target: BasicBlock,
893         unwind: Option<BasicBlock>,
894     },
895
896     /// Block ends with a call of a converging function
897     Call {
898         /// The function that’s being called
899         func: Operand<'tcx>,
900         /// Arguments the function is called with.
901         /// These are owned by the callee, which is free to modify them.
902         /// This allows the memory occupied by "by-value" arguments to be
903         /// reused across function calls without duplicating the contents.
904         args: Vec<Operand<'tcx>>,
905         /// Destination for the return value. If some, the call is converging.
906         destination: Option<(Place<'tcx>, BasicBlock)>,
907         /// Cleanups to be done if the call unwinds.
908         cleanup: Option<BasicBlock>,
909     },
910
911     /// Jump to the target if the condition has the expected value,
912     /// otherwise panic with a message and a cleanup target.
913     Assert {
914         cond: Operand<'tcx>,
915         expected: bool,
916         msg: AssertMessage<'tcx>,
917         target: BasicBlock,
918         cleanup: Option<BasicBlock>,
919     },
920
921     /// A suspend point
922     Yield {
923         /// The value to return
924         value: Operand<'tcx>,
925         /// Where to resume to
926         resume: BasicBlock,
927         /// Cleanup to be done if the generator is dropped at this suspend point
928         drop: Option<BasicBlock>,
929     },
930
931     /// Indicates the end of the dropping of a generator
932     GeneratorDrop,
933
934     /// A block where control flow only ever takes one real path, but borrowck
935     /// needs to be more conservative.
936     FalseEdges {
937         /// The target normal control flow will take
938         real_target: BasicBlock,
939         /// The list of blocks control flow could conceptually take, but won't
940         /// in practice
941         imaginary_targets: Vec<BasicBlock>,
942     },
943     /// A terminator for blocks that only take one path in reality, but where we
944     /// reserve the right to unwind in borrowck, even if it won't happen in practice.
945     /// This can arise in infinite loops with no function calls for example.
946     FalseUnwind {
947         /// The target normal control flow will take
948         real_target: BasicBlock,
949         /// The imaginary cleanup block link. This particular path will never be taken
950         /// in practice, but in order to avoid fragility we want to always
951         /// consider it in borrowck. We don't want to accept programs which
952         /// pass borrowck only when panic=abort or some assertions are disabled
953         /// due to release vs. debug mode builds. This needs to be an Option because
954         /// of the remove_noop_landing_pads and no_landing_pads passes
955         unwind: Option<BasicBlock>,
956     },
957 }
958
959 pub type Successors<'a> =
960     iter::Chain<option::IntoIter<&'a BasicBlock>, slice::Iter<'a, BasicBlock>>;
961 pub type SuccessorsMut<'a> =
962     iter::Chain<option::IntoIter<&'a mut BasicBlock>, slice::IterMut<'a, BasicBlock>>;
963
964 impl<'tcx> Terminator<'tcx> {
965     pub fn successors(&self) -> Successors {
966         self.kind.successors()
967     }
968
969     pub fn successors_mut(&mut self) -> SuccessorsMut {
970         self.kind.successors_mut()
971     }
972
973     pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> {
974         self.kind.unwind_mut()
975     }
976 }
977
978 impl<'tcx> TerminatorKind<'tcx> {
979     pub fn if_<'a, 'gcx>(
980         tcx: TyCtxt<'a, 'gcx, 'tcx>,
981         cond: Operand<'tcx>,
982         t: BasicBlock,
983         f: BasicBlock,
984     ) -> TerminatorKind<'tcx> {
985         static BOOL_SWITCH_FALSE: &'static [u128] = &[0];
986         TerminatorKind::SwitchInt {
987             discr: cond,
988             switch_ty: tcx.types.bool,
989             values: From::from(BOOL_SWITCH_FALSE),
990             targets: vec![f, t],
991         }
992     }
993
994     pub fn successors(&self) -> Successors {
995         use self::TerminatorKind::*;
996         match *self {
997             Resume
998             | Abort
999             | GeneratorDrop
1000             | Return
1001             | Unreachable
1002             | Call {
1003                 destination: None,
1004                 cleanup: None,
1005                 ..
1006             } => None.into_iter().chain(&[]),
1007             Goto { target: ref t }
1008             | Call {
1009                 destination: None,
1010                 cleanup: Some(ref t),
1011                 ..
1012             }
1013             | Call {
1014                 destination: Some((_, ref t)),
1015                 cleanup: None,
1016                 ..
1017             }
1018             | Yield {
1019                 resume: ref t,
1020                 drop: None,
1021                 ..
1022             }
1023             | DropAndReplace {
1024                 target: ref t,
1025                 unwind: None,
1026                 ..
1027             }
1028             | Drop {
1029                 target: ref t,
1030                 unwind: None,
1031                 ..
1032             }
1033             | Assert {
1034                 target: ref t,
1035                 cleanup: None,
1036                 ..
1037             }
1038             | FalseUnwind {
1039                 real_target: ref t,
1040                 unwind: None,
1041             } => Some(t).into_iter().chain(&[]),
1042             Call {
1043                 destination: Some((_, ref t)),
1044                 cleanup: Some(ref u),
1045                 ..
1046             }
1047             | Yield {
1048                 resume: ref t,
1049                 drop: Some(ref u),
1050                 ..
1051             }
1052             | DropAndReplace {
1053                 target: ref t,
1054                 unwind: Some(ref u),
1055                 ..
1056             }
1057             | Drop {
1058                 target: ref t,
1059                 unwind: Some(ref u),
1060                 ..
1061             }
1062             | Assert {
1063                 target: ref t,
1064                 cleanup: Some(ref u),
1065                 ..
1066             }
1067             | FalseUnwind {
1068                 real_target: ref t,
1069                 unwind: Some(ref u),
1070             } => Some(t).into_iter().chain(slice::from_ref(u)),
1071             SwitchInt { ref targets, .. } => None.into_iter().chain(&targets[..]),
1072             FalseEdges {
1073                 ref real_target,
1074                 ref imaginary_targets,
1075             } => Some(real_target).into_iter().chain(&imaginary_targets[..]),
1076         }
1077     }
1078
1079     pub fn successors_mut(&mut self) -> SuccessorsMut {
1080         use self::TerminatorKind::*;
1081         match *self {
1082             Resume
1083             | Abort
1084             | GeneratorDrop
1085             | Return
1086             | Unreachable
1087             | Call {
1088                 destination: None,
1089                 cleanup: None,
1090                 ..
1091             } => None.into_iter().chain(&mut []),
1092             Goto { target: ref mut t }
1093             | Call {
1094                 destination: None,
1095                 cleanup: Some(ref mut t),
1096                 ..
1097             }
1098             | Call {
1099                 destination: Some((_, ref mut t)),
1100                 cleanup: None,
1101                 ..
1102             }
1103             | Yield {
1104                 resume: ref mut t,
1105                 drop: None,
1106                 ..
1107             }
1108             | DropAndReplace {
1109                 target: ref mut t,
1110                 unwind: None,
1111                 ..
1112             }
1113             | Drop {
1114                 target: ref mut t,
1115                 unwind: None,
1116                 ..
1117             }
1118             | Assert {
1119                 target: ref mut t,
1120                 cleanup: None,
1121                 ..
1122             }
1123             | FalseUnwind {
1124                 real_target: ref mut t,
1125                 unwind: None,
1126             } => Some(t).into_iter().chain(&mut []),
1127             Call {
1128                 destination: Some((_, ref mut t)),
1129                 cleanup: Some(ref mut u),
1130                 ..
1131             }
1132             | Yield {
1133                 resume: ref mut t,
1134                 drop: Some(ref mut u),
1135                 ..
1136             }
1137             | DropAndReplace {
1138                 target: ref mut t,
1139                 unwind: Some(ref mut u),
1140                 ..
1141             }
1142             | Drop {
1143                 target: ref mut t,
1144                 unwind: Some(ref mut u),
1145                 ..
1146             }
1147             | Assert {
1148                 target: ref mut t,
1149                 cleanup: Some(ref mut u),
1150                 ..
1151             }
1152             | FalseUnwind {
1153                 real_target: ref mut t,
1154                 unwind: Some(ref mut u),
1155             } => Some(t).into_iter().chain(slice::from_mut(u)),
1156             SwitchInt {
1157                 ref mut targets, ..
1158             } => None.into_iter().chain(&mut targets[..]),
1159             FalseEdges {
1160                 ref mut real_target,
1161                 ref mut imaginary_targets,
1162             } => Some(real_target)
1163                 .into_iter()
1164                 .chain(&mut imaginary_targets[..]),
1165         }
1166     }
1167
1168     pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> {
1169         match *self {
1170             TerminatorKind::Goto { .. }
1171             | TerminatorKind::Resume
1172             | TerminatorKind::Abort
1173             | TerminatorKind::Return
1174             | TerminatorKind::Unreachable
1175             | TerminatorKind::GeneratorDrop
1176             | TerminatorKind::Yield { .. }
1177             | TerminatorKind::SwitchInt { .. }
1178             | TerminatorKind::FalseEdges { .. } => None,
1179             TerminatorKind::Call {
1180                 cleanup: ref mut unwind,
1181                 ..
1182             }
1183             | TerminatorKind::Assert {
1184                 cleanup: ref mut unwind,
1185                 ..
1186             }
1187             | TerminatorKind::DropAndReplace { ref mut unwind, .. }
1188             | TerminatorKind::Drop { ref mut unwind, .. }
1189             | TerminatorKind::FalseUnwind { ref mut unwind, .. } => Some(unwind),
1190         }
1191     }
1192 }
1193
1194 impl<'tcx> BasicBlockData<'tcx> {
1195     pub fn new(terminator: Option<Terminator<'tcx>>) -> BasicBlockData<'tcx> {
1196         BasicBlockData {
1197             statements: vec![],
1198             terminator,
1199             is_cleanup: false,
1200         }
1201     }
1202
1203     /// Accessor for terminator.
1204     ///
1205     /// Terminator may not be None after construction of the basic block is complete. This accessor
1206     /// provides a convenience way to reach the terminator.
1207     pub fn terminator(&self) -> &Terminator<'tcx> {
1208         self.terminator.as_ref().expect("invalid terminator state")
1209     }
1210
1211     pub fn terminator_mut(&mut self) -> &mut Terminator<'tcx> {
1212         self.terminator.as_mut().expect("invalid terminator state")
1213     }
1214
1215     pub fn retain_statements<F>(&mut self, mut f: F)
1216     where
1217         F: FnMut(&mut Statement) -> bool,
1218     {
1219         for s in &mut self.statements {
1220             if !f(s) {
1221                 s.make_nop();
1222             }
1223         }
1224     }
1225
1226     pub fn expand_statements<F, I>(&mut self, mut f: F)
1227     where
1228         F: FnMut(&mut Statement<'tcx>) -> Option<I>,
1229         I: iter::TrustedLen<Item = Statement<'tcx>>,
1230     {
1231         // Gather all the iterators we'll need to splice in, and their positions.
1232         let mut splices: Vec<(usize, I)> = vec![];
1233         let mut extra_stmts = 0;
1234         for (i, s) in self.statements.iter_mut().enumerate() {
1235             if let Some(mut new_stmts) = f(s) {
1236                 if let Some(first) = new_stmts.next() {
1237                     // We can already store the first new statement.
1238                     *s = first;
1239
1240                     // Save the other statements for optimized splicing.
1241                     let remaining = new_stmts.size_hint().0;
1242                     if remaining > 0 {
1243                         splices.push((i + 1 + extra_stmts, new_stmts));
1244                         extra_stmts += remaining;
1245                     }
1246                 } else {
1247                     s.make_nop();
1248                 }
1249             }
1250         }
1251
1252         // Splice in the new statements, from the end of the block.
1253         // FIXME(eddyb) This could be more efficient with a "gap buffer"
1254         // where a range of elements ("gap") is left uninitialized, with
1255         // splicing adding new elements to the end of that gap and moving
1256         // existing elements from before the gap to the end of the gap.
1257         // For now, this is safe code, emulating a gap but initializing it.
1258         let mut gap = self.statements.len()..self.statements.len() + extra_stmts;
1259         self.statements.resize(
1260             gap.end,
1261             Statement {
1262                 source_info: SourceInfo {
1263                     span: DUMMY_SP,
1264                     scope: OUTERMOST_SOURCE_SCOPE,
1265                 },
1266                 kind: StatementKind::Nop,
1267             },
1268         );
1269         for (splice_start, new_stmts) in splices.into_iter().rev() {
1270             let splice_end = splice_start + new_stmts.size_hint().0;
1271             while gap.end > splice_end {
1272                 gap.start -= 1;
1273                 gap.end -= 1;
1274                 self.statements.swap(gap.start, gap.end);
1275             }
1276             self.statements.splice(splice_start..splice_end, new_stmts);
1277             gap.end = splice_start;
1278         }
1279     }
1280
1281     pub fn visitable(&self, index: usize) -> &dyn MirVisitable<'tcx> {
1282         if index < self.statements.len() {
1283             &self.statements[index]
1284         } else {
1285             &self.terminator
1286         }
1287     }
1288 }
1289
1290 impl<'tcx> Debug for TerminatorKind<'tcx> {
1291     fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
1292         self.fmt_head(fmt)?;
1293         let successor_count = self.successors().count();
1294         let labels = self.fmt_successor_labels();
1295         assert_eq!(successor_count, labels.len());
1296
1297         match successor_count {
1298             0 => Ok(()),
1299
1300             1 => write!(fmt, " -> {:?}", self.successors().nth(0).unwrap()),
1301
1302             _ => {
1303                 write!(fmt, " -> [")?;
1304                 for (i, target) in self.successors().enumerate() {
1305                     if i > 0 {
1306                         write!(fmt, ", ")?;
1307                     }
1308                     write!(fmt, "{}: {:?}", labels[i], target)?;
1309                 }
1310                 write!(fmt, "]")
1311             }
1312         }
1313     }
1314 }
1315
1316 impl<'tcx> TerminatorKind<'tcx> {
1317     /// Write the "head" part of the terminator; that is, its name and the data it uses to pick the
1318     /// successor basic block, if any. The only information not included is the list of possible
1319     /// successors, which may be rendered differently between the text and the graphviz format.
1320     pub fn fmt_head<W: Write>(&self, fmt: &mut W) -> fmt::Result {
1321         use self::TerminatorKind::*;
1322         match *self {
1323             Goto { .. } => write!(fmt, "goto"),
1324             SwitchInt {
1325                 discr: ref place, ..
1326             } => write!(fmt, "switchInt({:?})", place),
1327             Return => write!(fmt, "return"),
1328             GeneratorDrop => write!(fmt, "generator_drop"),
1329             Resume => write!(fmt, "resume"),
1330             Abort => write!(fmt, "abort"),
1331             Yield { ref value, .. } => write!(fmt, "_1 = suspend({:?})", value),
1332             Unreachable => write!(fmt, "unreachable"),
1333             Drop { ref location, .. } => write!(fmt, "drop({:?})", location),
1334             DropAndReplace {
1335                 ref location,
1336                 ref value,
1337                 ..
1338             } => write!(fmt, "replace({:?} <- {:?})", location, value),
1339             Call {
1340                 ref func,
1341                 ref args,
1342                 ref destination,
1343                 ..
1344             } => {
1345                 if let Some((ref destination, _)) = *destination {
1346                     write!(fmt, "{:?} = ", destination)?;
1347                 }
1348                 write!(fmt, "{:?}(", func)?;
1349                 for (index, arg) in args.iter().enumerate() {
1350                     if index > 0 {
1351                         write!(fmt, ", ")?;
1352                     }
1353                     write!(fmt, "{:?}", arg)?;
1354                 }
1355                 write!(fmt, ")")
1356             }
1357             Assert {
1358                 ref cond,
1359                 expected,
1360                 ref msg,
1361                 ..
1362             } => {
1363                 write!(fmt, "assert(")?;
1364                 if !expected {
1365                     write!(fmt, "!")?;
1366                 }
1367                 write!(fmt, "{:?}, \"{:?}\")", cond, msg)
1368             }
1369             FalseEdges { .. } => write!(fmt, "falseEdges"),
1370             FalseUnwind { .. } => write!(fmt, "falseUnwind"),
1371         }
1372     }
1373
1374     /// Return the list of labels for the edges to the successor basic blocks.
1375     pub fn fmt_successor_labels(&self) -> Vec<Cow<'static, str>> {
1376         use self::TerminatorKind::*;
1377         match *self {
1378             Return | Resume | Abort | Unreachable | GeneratorDrop => vec![],
1379             Goto { .. } => vec!["".into()],
1380             SwitchInt {
1381                 ref values,
1382                 switch_ty,
1383                 ..
1384             } => {
1385                 let size = ty::tls::with(|tcx| {
1386                     let param_env = ty::ParamEnv::empty();
1387                     let switch_ty = tcx.lift_to_global(&switch_ty).unwrap();
1388                     tcx.layout_of(param_env.and(switch_ty)).unwrap().size
1389                 });
1390                 values
1391                     .iter()
1392                     .map(|&u| {
1393                         let mut s = String::new();
1394                         print_miri_value(
1395                             Value::Scalar(Scalar::Bits {
1396                                 bits: u,
1397                                 defined: size.bits() as u8,
1398                             }),
1399                             switch_ty,
1400                             &mut s,
1401                         ).unwrap();
1402                         s.into()
1403                     })
1404                     .chain(iter::once(String::from("otherwise").into()))
1405                     .collect()
1406             }
1407             Call {
1408                 destination: Some(_),
1409                 cleanup: Some(_),
1410                 ..
1411             } => vec!["return".into_cow(), "unwind".into_cow()],
1412             Call {
1413                 destination: Some(_),
1414                 cleanup: None,
1415                 ..
1416             } => vec!["return".into_cow()],
1417             Call {
1418                 destination: None,
1419                 cleanup: Some(_),
1420                 ..
1421             } => vec!["unwind".into_cow()],
1422             Call {
1423                 destination: None,
1424                 cleanup: None,
1425                 ..
1426             } => vec![],
1427             Yield { drop: Some(_), .. } => vec!["resume".into_cow(), "drop".into_cow()],
1428             Yield { drop: None, .. } => vec!["resume".into_cow()],
1429             DropAndReplace { unwind: None, .. } | Drop { unwind: None, .. } => {
1430                 vec!["return".into_cow()]
1431             }
1432             DropAndReplace {
1433                 unwind: Some(_), ..
1434             }
1435             | Drop {
1436                 unwind: Some(_), ..
1437             } => vec!["return".into_cow(), "unwind".into_cow()],
1438             Assert { cleanup: None, .. } => vec!["".into()],
1439             Assert { .. } => vec!["success".into_cow(), "unwind".into_cow()],
1440             FalseEdges {
1441                 ref imaginary_targets,
1442                 ..
1443             } => {
1444                 let mut l = vec!["real".into()];
1445                 l.resize(imaginary_targets.len() + 1, "imaginary".into());
1446                 l
1447             }
1448             FalseUnwind {
1449                 unwind: Some(_), ..
1450             } => vec!["real".into(), "cleanup".into()],
1451             FalseUnwind { unwind: None, .. } => vec!["real".into()],
1452         }
1453     }
1454 }
1455
1456 ///////////////////////////////////////////////////////////////////////////
1457 // Statements
1458
1459 #[derive(Clone, RustcEncodable, RustcDecodable)]
1460 pub struct Statement<'tcx> {
1461     pub source_info: SourceInfo,
1462     pub kind: StatementKind<'tcx>,
1463 }
1464
1465 impl<'tcx> Statement<'tcx> {
1466     /// Changes a statement to a nop. This is both faster than deleting instructions and avoids
1467     /// invalidating statement indices in `Location`s.
1468     pub fn make_nop(&mut self) {
1469         self.kind = StatementKind::Nop
1470     }
1471
1472     /// Changes a statement to a nop and returns the original statement.
1473     pub fn replace_nop(&mut self) -> Self {
1474         Statement {
1475             source_info: self.source_info,
1476             kind: mem::replace(&mut self.kind, StatementKind::Nop),
1477         }
1478     }
1479 }
1480
1481 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
1482 pub enum StatementKind<'tcx> {
1483     /// Write the RHS Rvalue to the LHS Place.
1484     Assign(Place<'tcx>, Rvalue<'tcx>),
1485
1486     /// This represents all the reading that a pattern match may do
1487     /// (e.g. inspecting constants and discriminant values).
1488     ReadForMatch(Place<'tcx>),
1489
1490     /// Write the discriminant for a variant to the enum Place.
1491     SetDiscriminant {
1492         place: Place<'tcx>,
1493         variant_index: usize,
1494     },
1495
1496     /// Start a live range for the storage of the local.
1497     StorageLive(Local),
1498
1499     /// End the current live range for the storage of the local.
1500     StorageDead(Local),
1501
1502     /// Execute a piece of inline Assembly.
1503     InlineAsm {
1504         asm: Box<InlineAsm>,
1505         outputs: Vec<Place<'tcx>>,
1506         inputs: Vec<Operand<'tcx>>,
1507     },
1508
1509     /// Assert the given places to be valid inhabitants of their type.  These statements are
1510     /// currently only interpreted by miri and only generated when "-Z mir-emit-validate" is passed.
1511     /// See <https://internals.rust-lang.org/t/types-as-contracts/5562/73> for more details.
1512     Validate(ValidationOp, Vec<ValidationOperand<'tcx, Place<'tcx>>>),
1513
1514     /// Mark one terminating point of a region scope (i.e. static region).
1515     /// (The starting point(s) arise implicitly from borrows.)
1516     EndRegion(region::Scope),
1517
1518     /// Encodes a user's type assertion. These need to be preserved intact so that NLL can respect
1519     /// them. For example:
1520     ///
1521     ///     let (a, b): (T, U) = y;
1522     ///
1523     /// Here we would insert a `UserAssertTy<(T, U)>(y)` instruction to check that the type of `y`
1524     /// is the right thing.
1525     ///
1526     /// `CanonicalTy` is used to capture "inference variables" from the user's types. For example:
1527     ///
1528     ///     let x: Vec<_> = ...;
1529     ///     let y: &u32 = ...;
1530     ///
1531     /// would result in `Vec<?0>` and `&'?0 u32` respectively (where `?0` is a canonicalized
1532     /// variable).
1533     UserAssertTy(CanonicalTy<'tcx>, Local),
1534
1535     /// No-op. Useful for deleting instructions without affecting statement indices.
1536     Nop,
1537 }
1538
1539 /// The `ValidationOp` describes what happens with each of the operands of a
1540 /// `Validate` statement.
1541 #[derive(Copy, Clone, RustcEncodable, RustcDecodable, PartialEq, Eq)]
1542 pub enum ValidationOp {
1543     /// Recursively traverse the place following the type and validate that all type
1544     /// invariants are maintained.  Furthermore, acquire exclusive/read-only access to the
1545     /// memory reachable from the place.
1546     Acquire,
1547     /// Recursive traverse the *mutable* part of the type and relinquish all exclusive
1548     /// access.
1549     Release,
1550     /// Recursive traverse the *mutable* part of the type and relinquish all exclusive
1551     /// access *until* the given region ends.  Then, access will be recovered.
1552     Suspend(region::Scope),
1553 }
1554
1555 impl Debug for ValidationOp {
1556     fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
1557         use self::ValidationOp::*;
1558         match *self {
1559             Acquire => write!(fmt, "Acquire"),
1560             Release => write!(fmt, "Release"),
1561             // (reuse lifetime rendering policy from ppaux.)
1562             Suspend(ref ce) => write!(fmt, "Suspend({})", ty::ReScope(*ce)),
1563         }
1564     }
1565 }
1566
1567 // This is generic so that it can be reused by miri
1568 #[derive(Clone, RustcEncodable, RustcDecodable)]
1569 pub struct ValidationOperand<'tcx, T> {
1570     pub place: T,
1571     pub ty: Ty<'tcx>,
1572     pub re: Option<region::Scope>,
1573     pub mutbl: hir::Mutability,
1574 }
1575
1576 impl<'tcx, T: Debug> Debug for ValidationOperand<'tcx, T> {
1577     fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
1578         write!(fmt, "{:?}: {:?}", self.place, self.ty)?;
1579         if let Some(ce) = self.re {
1580             // (reuse lifetime rendering policy from ppaux.)
1581             write!(fmt, "/{}", ty::ReScope(ce))?;
1582         }
1583         if let hir::MutImmutable = self.mutbl {
1584             write!(fmt, " (imm)")?;
1585         }
1586         Ok(())
1587     }
1588 }
1589
1590 impl<'tcx> Debug for Statement<'tcx> {
1591     fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
1592         use self::StatementKind::*;
1593         match self.kind {
1594             Assign(ref place, ref rv) => write!(fmt, "{:?} = {:?}", place, rv),
1595             ReadForMatch(ref place) => write!(fmt, "ReadForMatch({:?})", place),
1596             // (reuse lifetime rendering policy from ppaux.)
1597             EndRegion(ref ce) => write!(fmt, "EndRegion({})", ty::ReScope(*ce)),
1598             Validate(ref op, ref places) => write!(fmt, "Validate({:?}, {:?})", op, places),
1599             StorageLive(ref place) => write!(fmt, "StorageLive({:?})", place),
1600             StorageDead(ref place) => write!(fmt, "StorageDead({:?})", place),
1601             SetDiscriminant {
1602                 ref place,
1603                 variant_index,
1604             } => write!(fmt, "discriminant({:?}) = {:?}", place, variant_index),
1605             InlineAsm {
1606                 ref asm,
1607                 ref outputs,
1608                 ref inputs,
1609             } => write!(fmt, "asm!({:?} : {:?} : {:?})", asm, outputs, inputs),
1610             UserAssertTy(ref c_ty, ref local) => {
1611                 write!(fmt, "UserAssertTy({:?}, {:?})", c_ty, local)
1612             }
1613             Nop => write!(fmt, "nop"),
1614         }
1615     }
1616 }
1617
1618 ///////////////////////////////////////////////////////////////////////////
1619 // Places
1620
1621 /// A path to a value; something that can be evaluated without
1622 /// changing or disturbing program state.
1623 #[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
1624 pub enum Place<'tcx> {
1625     /// local variable
1626     Local(Local),
1627
1628     /// static or static mut variable
1629     Static(Box<Static<'tcx>>),
1630
1631     /// projection out of a place (access a field, deref a pointer, etc)
1632     Projection(Box<PlaceProjection<'tcx>>),
1633 }
1634
1635 /// The def-id of a static, along with its normalized type (which is
1636 /// stored to avoid requiring normalization when reading MIR).
1637 #[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
1638 pub struct Static<'tcx> {
1639     pub def_id: DefId,
1640     pub ty: Ty<'tcx>,
1641 }
1642
1643 impl_stable_hash_for!(struct Static<'tcx> {
1644     def_id,
1645     ty
1646 });
1647
1648 /// The `Projection` data structure defines things of the form `B.x`
1649 /// or `*B` or `B[index]`. Note that it is parameterized because it is
1650 /// shared between `Constant` and `Place`. See the aliases
1651 /// `PlaceProjection` etc below.
1652 #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
1653 pub struct Projection<'tcx, B, V, T> {
1654     pub base: B,
1655     pub elem: ProjectionElem<'tcx, V, T>,
1656 }
1657
1658 #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
1659 pub enum ProjectionElem<'tcx, V, T> {
1660     Deref,
1661     Field(Field, T),
1662     Index(V),
1663
1664     /// These indices are generated by slice patterns. Easiest to explain
1665     /// by example:
1666     ///
1667     /// ```
1668     /// [X, _, .._, _, _] => { offset: 0, min_length: 4, from_end: false },
1669     /// [_, X, .._, _, _] => { offset: 1, min_length: 4, from_end: false },
1670     /// [_, _, .._, X, _] => { offset: 2, min_length: 4, from_end: true },
1671     /// [_, _, .._, _, X] => { offset: 1, min_length: 4, from_end: true },
1672     /// ```
1673     ConstantIndex {
1674         /// index or -index (in Python terms), depending on from_end
1675         offset: u32,
1676         /// thing being indexed must be at least this long
1677         min_length: u32,
1678         /// counting backwards from end?
1679         from_end: bool,
1680     },
1681
1682     /// These indices are generated by slice patterns.
1683     ///
1684     /// slice[from:-to] in Python terms.
1685     Subslice {
1686         from: u32,
1687         to: u32,
1688     },
1689
1690     /// "Downcast" to a variant of an ADT. Currently, we only introduce
1691     /// this for ADTs with more than one variant. It may be better to
1692     /// just introduce it always, or always for enums.
1693     Downcast(&'tcx AdtDef, usize),
1694 }
1695
1696 /// Alias for projections as they appear in places, where the base is a place
1697 /// and the index is a local.
1698 pub type PlaceProjection<'tcx> = Projection<'tcx, Place<'tcx>, Local, Ty<'tcx>>;
1699
1700 /// Alias for projections as they appear in places, where the base is a place
1701 /// and the index is a local.
1702 pub type PlaceElem<'tcx> = ProjectionElem<'tcx, Local, Ty<'tcx>>;
1703
1704 newtype_index!(Field { DEBUG_FORMAT = "field[{}]" });
1705
1706 impl<'tcx> Place<'tcx> {
1707     pub fn field(self, f: Field, ty: Ty<'tcx>) -> Place<'tcx> {
1708         self.elem(ProjectionElem::Field(f, ty))
1709     }
1710
1711     pub fn deref(self) -> Place<'tcx> {
1712         self.elem(ProjectionElem::Deref)
1713     }
1714
1715     pub fn downcast(self, adt_def: &'tcx AdtDef, variant_index: usize) -> Place<'tcx> {
1716         self.elem(ProjectionElem::Downcast(adt_def, variant_index))
1717     }
1718
1719     pub fn index(self, index: Local) -> Place<'tcx> {
1720         self.elem(ProjectionElem::Index(index))
1721     }
1722
1723     pub fn elem(self, elem: PlaceElem<'tcx>) -> Place<'tcx> {
1724         Place::Projection(Box::new(PlaceProjection { base: self, elem }))
1725     }
1726 }
1727
1728 impl<'tcx> Debug for Place<'tcx> {
1729     fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
1730         use self::Place::*;
1731
1732         match *self {
1733             Local(id) => write!(fmt, "{:?}", id),
1734             Static(box self::Static { def_id, ty }) => write!(
1735                 fmt,
1736                 "({}: {:?})",
1737                 ty::tls::with(|tcx| tcx.item_path_str(def_id)),
1738                 ty
1739             ),
1740             Projection(ref data) => match data.elem {
1741                 ProjectionElem::Downcast(ref adt_def, index) => {
1742                     write!(fmt, "({:?} as {})", data.base, adt_def.variants[index].name)
1743                 }
1744                 ProjectionElem::Deref => write!(fmt, "(*{:?})", data.base),
1745                 ProjectionElem::Field(field, ty) => {
1746                     write!(fmt, "({:?}.{:?}: {:?})", data.base, field.index(), ty)
1747                 }
1748                 ProjectionElem::Index(ref index) => write!(fmt, "{:?}[{:?}]", data.base, index),
1749                 ProjectionElem::ConstantIndex {
1750                     offset,
1751                     min_length,
1752                     from_end: false,
1753                 } => write!(fmt, "{:?}[{:?} of {:?}]", data.base, offset, min_length),
1754                 ProjectionElem::ConstantIndex {
1755                     offset,
1756                     min_length,
1757                     from_end: true,
1758                 } => write!(fmt, "{:?}[-{:?} of {:?}]", data.base, offset, min_length),
1759                 ProjectionElem::Subslice { from, to } if to == 0 => {
1760                     write!(fmt, "{:?}[{:?}:]", data.base, from)
1761                 }
1762                 ProjectionElem::Subslice { from, to } if from == 0 => {
1763                     write!(fmt, "{:?}[:-{:?}]", data.base, to)
1764                 }
1765                 ProjectionElem::Subslice { from, to } => {
1766                     write!(fmt, "{:?}[{:?}:-{:?}]", data.base, from, to)
1767                 }
1768             },
1769         }
1770     }
1771 }
1772
1773 ///////////////////////////////////////////////////////////////////////////
1774 // Scopes
1775
1776 newtype_index!(SourceScope
1777     {
1778         DEBUG_FORMAT = "scope[{}]",
1779         const OUTERMOST_SOURCE_SCOPE = 0,
1780     });
1781
1782 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
1783 pub struct SourceScopeData {
1784     pub span: Span,
1785     pub parent_scope: Option<SourceScope>,
1786 }
1787
1788 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
1789 pub struct SourceScopeLocalData {
1790     /// A NodeId with lint levels equivalent to this scope's lint levels.
1791     pub lint_root: ast::NodeId,
1792     /// The unsafe block that contains this node.
1793     pub safety: Safety,
1794 }
1795
1796 ///////////////////////////////////////////////////////////////////////////
1797 // Operands
1798
1799 /// These are values that can appear inside an rvalue (or an index
1800 /// place). They are intentionally limited to prevent rvalues from
1801 /// being nested in one another.
1802 #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)]
1803 pub enum Operand<'tcx> {
1804     /// Copy: The value must be available for use afterwards.
1805     ///
1806     /// This implies that the type of the place must be `Copy`; this is true
1807     /// by construction during build, but also checked by the MIR type checker.
1808     Copy(Place<'tcx>),
1809     /// Move: The value (including old borrows of it) will not be used again.
1810     ///
1811     /// Safe for values of all types (modulo future developments towards `?Move`).
1812     /// Correct usage patterns are enforced by the borrow checker for safe code.
1813     /// `Copy` may be converted to `Move` to enable "last-use" optimizations.
1814     Move(Place<'tcx>),
1815     Constant(Box<Constant<'tcx>>),
1816 }
1817
1818 impl<'tcx> Debug for Operand<'tcx> {
1819     fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
1820         use self::Operand::*;
1821         match *self {
1822             Constant(ref a) => write!(fmt, "{:?}", a),
1823             Copy(ref place) => write!(fmt, "{:?}", place),
1824             Move(ref place) => write!(fmt, "move {:?}", place),
1825         }
1826     }
1827 }
1828
1829 impl<'tcx> Operand<'tcx> {
1830     pub fn function_handle<'a>(
1831         tcx: TyCtxt<'a, 'tcx, 'tcx>,
1832         def_id: DefId,
1833         substs: &'tcx Substs<'tcx>,
1834         span: Span,
1835     ) -> Self {
1836         let ty = tcx.type_of(def_id).subst(tcx, substs);
1837         Operand::Constant(box Constant {
1838             span,
1839             ty,
1840             literal: Literal::Value {
1841                 value: ty::Const::zero_sized(tcx, ty),
1842             },
1843         })
1844     }
1845
1846     pub fn to_copy(&self) -> Self {
1847         match *self {
1848             Operand::Copy(_) | Operand::Constant(_) => self.clone(),
1849             Operand::Move(ref place) => Operand::Copy(place.clone()),
1850         }
1851     }
1852 }
1853
1854 ///////////////////////////////////////////////////////////////////////////
1855 /// Rvalues
1856
1857 #[derive(Clone, RustcEncodable, RustcDecodable)]
1858 pub enum Rvalue<'tcx> {
1859     /// x (either a move or copy, depending on type of x)
1860     Use(Operand<'tcx>),
1861
1862     /// [x; 32]
1863     Repeat(Operand<'tcx>, u64),
1864
1865     /// &x or &mut x
1866     Ref(Region<'tcx>, BorrowKind, Place<'tcx>),
1867
1868     /// length of a [X] or [X;n] value
1869     Len(Place<'tcx>),
1870
1871     Cast(CastKind, Operand<'tcx>, Ty<'tcx>),
1872
1873     BinaryOp(BinOp, Operand<'tcx>, Operand<'tcx>),
1874     CheckedBinaryOp(BinOp, Operand<'tcx>, Operand<'tcx>),
1875
1876     NullaryOp(NullOp, Ty<'tcx>),
1877     UnaryOp(UnOp, Operand<'tcx>),
1878
1879     /// Read the discriminant of an ADT.
1880     ///
1881     /// Undefined (i.e. no effort is made to make it defined, but there’s no reason why it cannot
1882     /// be defined to return, say, a 0) if ADT is not an enum.
1883     Discriminant(Place<'tcx>),
1884
1885     /// Create an aggregate value, like a tuple or struct.  This is
1886     /// only needed because we want to distinguish `dest = Foo { x:
1887     /// ..., y: ... }` from `dest.x = ...; dest.y = ...;` in the case
1888     /// that `Foo` has a destructor. These rvalues can be optimized
1889     /// away after type-checking and before lowering.
1890     Aggregate(Box<AggregateKind<'tcx>>, Vec<Operand<'tcx>>),
1891 }
1892
1893 #[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
1894 pub enum CastKind {
1895     Misc,
1896
1897     /// Convert unique, zero-sized type for a fn to fn()
1898     ReifyFnPointer,
1899
1900     /// Convert non capturing closure to fn()
1901     ClosureFnPointer,
1902
1903     /// Convert safe fn() to unsafe fn()
1904     UnsafeFnPointer,
1905
1906     /// "Unsize" -- convert a thin-or-fat pointer to a fat pointer.
1907     /// codegen must figure out the details once full monomorphization
1908     /// is known. For example, this could be used to cast from a
1909     /// `&[i32;N]` to a `&[i32]`, or a `Box<T>` to a `Box<Trait>`
1910     /// (presuming `T: Trait`).
1911     Unsize,
1912 }
1913
1914 #[derive(Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
1915 pub enum AggregateKind<'tcx> {
1916     /// The type is of the element
1917     Array(Ty<'tcx>),
1918     Tuple,
1919
1920     /// The second field is the variant index. It's equal to 0 for struct
1921     /// and union expressions. The fourth field is
1922     /// active field number and is present only for union expressions
1923     /// -- e.g. for a union expression `SomeUnion { c: .. }`, the
1924     /// active field index would identity the field `c`
1925     Adt(&'tcx AdtDef, usize, &'tcx Substs<'tcx>, Option<usize>),
1926
1927     Closure(DefId, ClosureSubsts<'tcx>),
1928     Generator(DefId, GeneratorSubsts<'tcx>, hir::GeneratorMovability),
1929 }
1930
1931 #[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
1932 pub enum BinOp {
1933     /// The `+` operator (addition)
1934     Add,
1935     /// The `-` operator (subtraction)
1936     Sub,
1937     /// The `*` operator (multiplication)
1938     Mul,
1939     /// The `/` operator (division)
1940     Div,
1941     /// The `%` operator (modulus)
1942     Rem,
1943     /// The `^` operator (bitwise xor)
1944     BitXor,
1945     /// The `&` operator (bitwise and)
1946     BitAnd,
1947     /// The `|` operator (bitwise or)
1948     BitOr,
1949     /// The `<<` operator (shift left)
1950     Shl,
1951     /// The `>>` operator (shift right)
1952     Shr,
1953     /// The `==` operator (equality)
1954     Eq,
1955     /// The `<` operator (less than)
1956     Lt,
1957     /// The `<=` operator (less than or equal to)
1958     Le,
1959     /// The `!=` operator (not equal to)
1960     Ne,
1961     /// The `>=` operator (greater than or equal to)
1962     Ge,
1963     /// The `>` operator (greater than)
1964     Gt,
1965     /// The `ptr.offset` operator
1966     Offset,
1967 }
1968
1969 impl BinOp {
1970     pub fn is_checkable(self) -> bool {
1971         use self::BinOp::*;
1972         match self {
1973             Add | Sub | Mul | Shl | Shr => true,
1974             _ => false,
1975         }
1976     }
1977 }
1978
1979 #[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
1980 pub enum NullOp {
1981     /// Return the size of a value of that type
1982     SizeOf,
1983     /// Create a new uninitialized box for a value of that type
1984     Box,
1985 }
1986
1987 #[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
1988 pub enum UnOp {
1989     /// The `!` operator for logical inversion
1990     Not,
1991     /// The `-` operator for negation
1992     Neg,
1993 }
1994
1995 impl<'tcx> Debug for Rvalue<'tcx> {
1996     fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
1997         use self::Rvalue::*;
1998
1999         match *self {
2000             Use(ref place) => write!(fmt, "{:?}", place),
2001             Repeat(ref a, ref b) => write!(fmt, "[{:?}; {:?}]", a, b),
2002             Len(ref a) => write!(fmt, "Len({:?})", a),
2003             Cast(ref kind, ref place, ref ty) => {
2004                 write!(fmt, "{:?} as {:?} ({:?})", place, ty, kind)
2005             }
2006             BinaryOp(ref op, ref a, ref b) => write!(fmt, "{:?}({:?}, {:?})", op, a, b),
2007             CheckedBinaryOp(ref op, ref a, ref b) => {
2008                 write!(fmt, "Checked{:?}({:?}, {:?})", op, a, b)
2009             }
2010             UnaryOp(ref op, ref a) => write!(fmt, "{:?}({:?})", op, a),
2011             Discriminant(ref place) => write!(fmt, "discriminant({:?})", place),
2012             NullaryOp(ref op, ref t) => write!(fmt, "{:?}({:?})", op, t),
2013             Ref(region, borrow_kind, ref place) => {
2014                 let kind_str = match borrow_kind {
2015                     BorrowKind::Shared => "",
2016                     BorrowKind::Mut { .. } | BorrowKind::Unique => "mut ",
2017                 };
2018
2019                 // When printing regions, add trailing space if necessary.
2020                 let region = if ppaux::verbose() || ppaux::identify_regions() {
2021                     let mut region = format!("{}", region);
2022                     if region.len() > 0 {
2023                         region.push(' ');
2024                     }
2025                     region
2026                 } else {
2027                     // Do not even print 'static
2028                     "".to_owned()
2029                 };
2030                 write!(fmt, "&{}{}{:?}", region, kind_str, place)
2031             }
2032
2033             Aggregate(ref kind, ref places) => {
2034                 fn fmt_tuple(fmt: &mut Formatter, places: &[Operand]) -> fmt::Result {
2035                     let mut tuple_fmt = fmt.debug_tuple("");
2036                     for place in places {
2037                         tuple_fmt.field(place);
2038                     }
2039                     tuple_fmt.finish()
2040                 }
2041
2042                 match **kind {
2043                     AggregateKind::Array(_) => write!(fmt, "{:?}", places),
2044
2045                     AggregateKind::Tuple => match places.len() {
2046                         0 => write!(fmt, "()"),
2047                         1 => write!(fmt, "({:?},)", places[0]),
2048                         _ => fmt_tuple(fmt, places),
2049                     },
2050
2051                     AggregateKind::Adt(adt_def, variant, substs, _) => {
2052                         let variant_def = &adt_def.variants[variant];
2053
2054                         ppaux::parameterized(fmt, substs, variant_def.did, &[])?;
2055
2056                         match variant_def.ctor_kind {
2057                             CtorKind::Const => Ok(()),
2058                             CtorKind::Fn => fmt_tuple(fmt, places),
2059                             CtorKind::Fictive => {
2060                                 let mut struct_fmt = fmt.debug_struct("");
2061                                 for (field, place) in variant_def.fields.iter().zip(places) {
2062                                     struct_fmt.field(&field.ident.as_str(), place);
2063                                 }
2064                                 struct_fmt.finish()
2065                             }
2066                         }
2067                     }
2068
2069                     AggregateKind::Closure(def_id, _) => ty::tls::with(|tcx| {
2070                         if let Some(node_id) = tcx.hir.as_local_node_id(def_id) {
2071                             let name = if tcx.sess.opts.debugging_opts.span_free_formats {
2072                                 format!("[closure@{:?}]", node_id)
2073                             } else {
2074                                 format!("[closure@{:?}]", tcx.hir.span(node_id))
2075                             };
2076                             let mut struct_fmt = fmt.debug_struct(&name);
2077
2078                             tcx.with_freevars(node_id, |freevars| {
2079                                 for (freevar, place) in freevars.iter().zip(places) {
2080                                     let var_name = tcx.hir.name(freevar.var_id());
2081                                     struct_fmt.field(&var_name.as_str(), place);
2082                                 }
2083                             });
2084
2085                             struct_fmt.finish()
2086                         } else {
2087                             write!(fmt, "[closure]")
2088                         }
2089                     }),
2090
2091                     AggregateKind::Generator(def_id, _, _) => ty::tls::with(|tcx| {
2092                         if let Some(node_id) = tcx.hir.as_local_node_id(def_id) {
2093                             let name = format!("[generator@{:?}]", tcx.hir.span(node_id));
2094                             let mut struct_fmt = fmt.debug_struct(&name);
2095
2096                             tcx.with_freevars(node_id, |freevars| {
2097                                 for (freevar, place) in freevars.iter().zip(places) {
2098                                     let var_name = tcx.hir.name(freevar.var_id());
2099                                     struct_fmt.field(&var_name.as_str(), place);
2100                                 }
2101                                 struct_fmt.field("$state", &places[freevars.len()]);
2102                                 for i in (freevars.len() + 1)..places.len() {
2103                                     struct_fmt
2104                                         .field(&format!("${}", i - freevars.len() - 1), &places[i]);
2105                                 }
2106                             });
2107
2108                             struct_fmt.finish()
2109                         } else {
2110                             write!(fmt, "[generator]")
2111                         }
2112                     }),
2113                 }
2114             }
2115         }
2116     }
2117 }
2118
2119 ///////////////////////////////////////////////////////////////////////////
2120 /// Constants
2121 ///
2122 /// Two constants are equal if they are the same constant. Note that
2123 /// this does not necessarily mean that they are "==" in Rust -- in
2124 /// particular one must be wary of `NaN`!
2125
2126 #[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
2127 pub struct Constant<'tcx> {
2128     pub span: Span,
2129     pub ty: Ty<'tcx>,
2130     pub literal: Literal<'tcx>,
2131 }
2132
2133 newtype_index!(Promoted { DEBUG_FORMAT = "promoted[{}]" });
2134
2135 #[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
2136 pub enum Literal<'tcx> {
2137     Value {
2138         value: &'tcx ty::Const<'tcx>,
2139     },
2140     Promoted {
2141         // Index into the `promoted` vector of `Mir`.
2142         index: Promoted,
2143     },
2144 }
2145
2146 impl<'tcx> Debug for Constant<'tcx> {
2147     fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
2148         write!(fmt, "{:?}", self.literal)
2149     }
2150 }
2151
2152 impl<'tcx> Debug for Literal<'tcx> {
2153     fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
2154         use self::Literal::*;
2155         match *self {
2156             Value { value } => {
2157                 write!(fmt, "const ")?;
2158                 fmt_const_val(fmt, value)
2159             }
2160             Promoted { index } => write!(fmt, "{:?}", index),
2161         }
2162     }
2163 }
2164
2165 /// Write a `ConstVal` in a way closer to the original source code than the `Debug` output.
2166 pub fn fmt_const_val<W: Write>(fmt: &mut W, const_val: &ty::Const) -> fmt::Result {
2167     use middle::const_val::ConstVal;
2168     match const_val.val {
2169         ConstVal::Unevaluated(..) => write!(fmt, "{:?}", const_val),
2170         ConstVal::Value(val) => {
2171             if let Some(value) = val.to_byval_value() {
2172                 print_miri_value(value, const_val.ty, fmt)
2173             } else {
2174                 write!(fmt, "{:?}:{}", val, const_val.ty)
2175             }
2176         }
2177     }
2178 }
2179
2180 pub fn print_miri_value<W: Write>(value: Value, ty: Ty, f: &mut W) -> fmt::Result {
2181     use ty::TypeVariants::*;
2182     match (value, &ty.sty) {
2183         (Value::Scalar(Scalar::Bits { bits: 0, .. }), &TyBool) => write!(f, "false"),
2184         (Value::Scalar(Scalar::Bits { bits: 1, .. }), &TyBool) => write!(f, "true"),
2185         (Value::Scalar(Scalar::Bits { bits, .. }), &TyFloat(ast::FloatTy::F32)) => {
2186             write!(f, "{}f32", Single::from_bits(bits))
2187         }
2188         (Value::Scalar(Scalar::Bits { bits, .. }), &TyFloat(ast::FloatTy::F64)) => {
2189             write!(f, "{}f64", Double::from_bits(bits))
2190         }
2191         (Value::Scalar(Scalar::Bits { bits, .. }), &TyUint(ui)) => write!(f, "{:?}{}", bits, ui),
2192         (Value::Scalar(Scalar::Bits { bits, .. }), &TyInt(i)) => {
2193             let bit_width = ty::tls::with(|tcx| {
2194                 let ty = tcx.lift_to_global(&ty).unwrap();
2195                 tcx.layout_of(ty::ParamEnv::empty().and(ty))
2196                     .unwrap()
2197                     .size
2198                     .bits()
2199             });
2200             let shift = 128 - bit_width;
2201             write!(f, "{:?}{}", ((bits as i128) << shift) >> shift, i)
2202         }
2203         (Value::Scalar(Scalar::Bits { bits, .. }), &TyChar) => {
2204             write!(f, "{:?}", ::std::char::from_u32(bits as u32).unwrap())
2205         }
2206         (_, &TyFnDef(did, _)) => write!(f, "{}", item_path_str(did)),
2207         (
2208             Value::ScalarPair(Scalar::Ptr(ptr), Scalar::Bits { bits: len, .. }),
2209             &TyRef(_, &ty::TyS { sty: TyStr, .. }, _),
2210         ) => ty::tls::with(|tcx| match tcx.alloc_map.lock().get(ptr.alloc_id) {
2211             Some(interpret::AllocType::Memory(alloc)) => {
2212                 assert_eq!(len as usize as u128, len);
2213                 let slice = &alloc.bytes[(ptr.offset.bytes() as usize)..][..(len as usize)];
2214                 let s = ::std::str::from_utf8(slice).expect("non utf8 str from miri");
2215                 write!(f, "{:?}", s)
2216             }
2217             _ => write!(f, "pointer to erroneous constant {:?}, {:?}", ptr, len),
2218         }),
2219         _ => write!(f, "{:?}:{}", value, ty),
2220     }
2221 }
2222
2223 fn item_path_str(def_id: DefId) -> String {
2224     ty::tls::with(|tcx| tcx.item_path_str(def_id))
2225 }
2226
2227 impl<'tcx> ControlFlowGraph for Mir<'tcx> {
2228     type Node = BasicBlock;
2229
2230     fn num_nodes(&self) -> usize {
2231         self.basic_blocks.len()
2232     }
2233
2234     fn start_node(&self) -> Self::Node {
2235         START_BLOCK
2236     }
2237
2238     fn predecessors<'graph>(
2239         &'graph self,
2240         node: Self::Node,
2241     ) -> <Self as GraphPredecessors<'graph>>::Iter {
2242         self.predecessors_for(node).clone().into_iter()
2243     }
2244     fn successors<'graph>(
2245         &'graph self,
2246         node: Self::Node,
2247     ) -> <Self as GraphSuccessors<'graph>>::Iter {
2248         self.basic_blocks[node].terminator().successors().cloned()
2249     }
2250 }
2251
2252 impl<'a, 'b> GraphPredecessors<'b> for Mir<'a> {
2253     type Item = BasicBlock;
2254     type Iter = IntoIter<BasicBlock>;
2255 }
2256
2257 impl<'a, 'b> GraphSuccessors<'b> for Mir<'a> {
2258     type Item = BasicBlock;
2259     type Iter = iter::Cloned<Successors<'b>>;
2260 }
2261
2262 #[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
2263 pub struct Location {
2264     /// the location is within this block
2265     pub block: BasicBlock,
2266
2267     /// the location is the start of the statement; or, if `statement_index`
2268     /// == num-statements, then the start of the terminator.
2269     pub statement_index: usize,
2270 }
2271
2272 impl fmt::Debug for Location {
2273     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2274         write!(fmt, "{:?}[{}]", self.block, self.statement_index)
2275     }
2276 }
2277
2278 impl Location {
2279     pub const START: Location = Location {
2280         block: START_BLOCK,
2281         statement_index: 0,
2282     };
2283
2284     /// Returns the location immediately after this one within the enclosing block.
2285     ///
2286     /// Note that if this location represents a terminator, then the
2287     /// resulting location would be out of bounds and invalid.
2288     pub fn successor_within_block(&self) -> Location {
2289         Location {
2290             block: self.block,
2291             statement_index: self.statement_index + 1,
2292         }
2293     }
2294
2295     pub fn dominates(&self, other: Location, dominators: &Dominators<BasicBlock>) -> bool {
2296         if self.block == other.block {
2297             self.statement_index <= other.statement_index
2298         } else {
2299             dominators.is_dominated_by(other.block, self.block)
2300         }
2301     }
2302 }
2303
2304 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
2305 pub enum UnsafetyViolationKind {
2306     General,
2307     ExternStatic(ast::NodeId),
2308     BorrowPacked(ast::NodeId),
2309 }
2310
2311 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
2312 pub struct UnsafetyViolation {
2313     pub source_info: SourceInfo,
2314     pub description: InternedString,
2315     pub kind: UnsafetyViolationKind,
2316 }
2317
2318 #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
2319 pub struct UnsafetyCheckResult {
2320     /// Violations that are propagated *upwards* from this function
2321     pub violations: Lrc<[UnsafetyViolation]>,
2322     /// unsafe blocks in this function, along with whether they are used. This is
2323     /// used for the "unused_unsafe" lint.
2324     pub unsafe_blocks: Lrc<[(ast::NodeId, bool)]>,
2325 }
2326
2327 /// The layout of generator state
2328 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
2329 pub struct GeneratorLayout<'tcx> {
2330     pub fields: Vec<LocalDecl<'tcx>>,
2331 }
2332
2333 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
2334 pub struct BorrowCheckResult<'gcx> {
2335     pub closure_requirements: Option<ClosureRegionRequirements<'gcx>>,
2336     pub used_mut_upvars: SmallVec<[Field; 8]>,
2337 }
2338
2339 /// After we borrow check a closure, we are left with various
2340 /// requirements that we have inferred between the free regions that
2341 /// appear in the closure's signature or on its field types.  These
2342 /// requirements are then verified and proved by the closure's
2343 /// creating function. This struct encodes those requirements.
2344 ///
2345 /// The requirements are listed as being between various
2346 /// `RegionVid`. The 0th region refers to `'static`; subsequent region
2347 /// vids refer to the free regions that appear in the closure (or
2348 /// generator's) type, in order of appearance. (This numbering is
2349 /// actually defined by the `UniversalRegions` struct in the NLL
2350 /// region checker. See for example
2351 /// `UniversalRegions::closure_mapping`.) Note that we treat the free
2352 /// regions in the closure's type "as if" they were erased, so their
2353 /// precise identity is not important, only their position.
2354 ///
2355 /// Example: If type check produces a closure with the closure substs:
2356 ///
2357 /// ```text
2358 /// ClosureSubsts = [
2359 ///     i8,                                  // the "closure kind"
2360 ///     for<'x> fn(&'a &'x u32) -> &'x u32,  // the "closure signature"
2361 ///     &'a String,                          // some upvar
2362 /// ]
2363 /// ```
2364 ///
2365 /// here, there is one unique free region (`'a`) but it appears
2366 /// twice. We would "renumber" each occurrence to a unique vid, as follows:
2367 ///
2368 /// ```text
2369 /// ClosureSubsts = [
2370 ///     i8,                                  // the "closure kind"
2371 ///     for<'x> fn(&'1 &'x u32) -> &'x u32,  // the "closure signature"
2372 ///     &'2 String,                          // some upvar
2373 /// ]
2374 /// ```
2375 ///
2376 /// Now the code might impose a requirement like `'1: '2`. When an
2377 /// instance of the closure is created, the corresponding free regions
2378 /// can be extracted from its type and constrained to have the given
2379 /// outlives relationship.
2380 ///
2381 /// In some cases, we have to record outlives requirements between
2382 /// types and regions as well. In that case, if those types include
2383 /// any regions, those regions are recorded as `ReClosureBound`
2384 /// instances assigned one of these same indices. Those regions will
2385 /// be substituted away by the creator. We use `ReClosureBound` in
2386 /// that case because the regions must be allocated in the global
2387 /// TyCtxt, and hence we cannot use `ReVar` (which is what we use
2388 /// internally within the rest of the NLL code).
2389 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
2390 pub struct ClosureRegionRequirements<'gcx> {
2391     /// The number of external regions defined on the closure.  In our
2392     /// example above, it would be 3 -- one for `'static`, then `'1`
2393     /// and `'2`. This is just used for a sanity check later on, to
2394     /// make sure that the number of regions we see at the callsite
2395     /// matches.
2396     pub num_external_vids: usize,
2397
2398     /// Requirements between the various free regions defined in
2399     /// indices.
2400     pub outlives_requirements: Vec<ClosureOutlivesRequirement<'gcx>>,
2401 }
2402
2403 /// Indicates an outlives constraint between a type or between two
2404 /// free-regions declared on the closure.
2405 #[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
2406 pub struct ClosureOutlivesRequirement<'tcx> {
2407     // This region or type ...
2408     pub subject: ClosureOutlivesSubject<'tcx>,
2409
2410     // .. must outlive this one.
2411     pub outlived_free_region: ty::RegionVid,
2412
2413     // If not, report an error here.
2414     pub blame_span: Span,
2415 }
2416
2417 /// The subject of a ClosureOutlivesRequirement -- that is, the thing
2418 /// that must outlive some region.
2419 #[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
2420 pub enum ClosureOutlivesSubject<'tcx> {
2421     /// Subject is a type, typically a type parameter, but could also
2422     /// be a projection. Indicates a requirement like `T: 'a` being
2423     /// passed to the caller, where the type here is `T`.
2424     ///
2425     /// The type here is guaranteed not to contain any free regions at
2426     /// present.
2427     Ty(Ty<'tcx>),
2428
2429     /// Subject is a free region from the closure. Indicates a requirement
2430     /// like `'a: 'b` being passed to the caller; the region here is `'a`.
2431     Region(ty::RegionVid),
2432 }
2433
2434 /*
2435  * TypeFoldable implementations for MIR types
2436  */
2437
2438 CloneTypeFoldableAndLiftImpls! {
2439     Mutability,
2440     SourceInfo,
2441     UpvarDecl,
2442     ValidationOp,
2443     SourceScope,
2444     SourceScopeData,
2445     SourceScopeLocalData,
2446 }
2447
2448 BraceStructTypeFoldableImpl! {
2449     impl<'tcx> TypeFoldable<'tcx> for Mir<'tcx> {
2450         basic_blocks,
2451         source_scopes,
2452         source_scope_local_data,
2453         promoted,
2454         yield_ty,
2455         generator_drop,
2456         generator_layout,
2457         local_decls,
2458         arg_count,
2459         upvar_decls,
2460         spread_arg,
2461         span,
2462         cache,
2463     }
2464 }
2465
2466 BraceStructTypeFoldableImpl! {
2467     impl<'tcx> TypeFoldable<'tcx> for GeneratorLayout<'tcx> {
2468         fields
2469     }
2470 }
2471
2472 BraceStructTypeFoldableImpl! {
2473     impl<'tcx> TypeFoldable<'tcx> for LocalDecl<'tcx> {
2474         mutability,
2475         is_user_variable,
2476         internal,
2477         ty,
2478         name,
2479         source_info,
2480         visibility_scope,
2481     }
2482 }
2483
2484 BraceStructTypeFoldableImpl! {
2485     impl<'tcx> TypeFoldable<'tcx> for BasicBlockData<'tcx> {
2486         statements,
2487         terminator,
2488         is_cleanup,
2489     }
2490 }
2491
2492 BraceStructTypeFoldableImpl! {
2493     impl<'tcx> TypeFoldable<'tcx> for ValidationOperand<'tcx, Place<'tcx>> {
2494         place, ty, re, mutbl
2495     }
2496 }
2497
2498 BraceStructTypeFoldableImpl! {
2499     impl<'tcx> TypeFoldable<'tcx> for Statement<'tcx> {
2500         source_info, kind
2501     }
2502 }
2503
2504 EnumTypeFoldableImpl! {
2505     impl<'tcx> TypeFoldable<'tcx> for StatementKind<'tcx> {
2506         (StatementKind::Assign)(a, b),
2507         (StatementKind::ReadForMatch)(place),
2508         (StatementKind::SetDiscriminant) { place, variant_index },
2509         (StatementKind::StorageLive)(a),
2510         (StatementKind::StorageDead)(a),
2511         (StatementKind::InlineAsm) { asm, outputs, inputs },
2512         (StatementKind::Validate)(a, b),
2513         (StatementKind::EndRegion)(a),
2514         (StatementKind::UserAssertTy)(a, b),
2515         (StatementKind::Nop),
2516     }
2517 }
2518
2519 EnumTypeFoldableImpl! {
2520     impl<'tcx, T> TypeFoldable<'tcx> for ClearCrossCrate<T> {
2521         (ClearCrossCrate::Clear),
2522         (ClearCrossCrate::Set)(a),
2523     } where T: TypeFoldable<'tcx>
2524 }
2525
2526 impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
2527     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
2528         use mir::TerminatorKind::*;
2529
2530         let kind = match self.kind {
2531             Goto { target } => Goto { target: target },
2532             SwitchInt {
2533                 ref discr,
2534                 switch_ty,
2535                 ref values,
2536                 ref targets,
2537             } => SwitchInt {
2538                 discr: discr.fold_with(folder),
2539                 switch_ty: switch_ty.fold_with(folder),
2540                 values: values.clone(),
2541                 targets: targets.clone(),
2542             },
2543             Drop {
2544                 ref location,
2545                 target,
2546                 unwind,
2547             } => Drop {
2548                 location: location.fold_with(folder),
2549                 target,
2550                 unwind,
2551             },
2552             DropAndReplace {
2553                 ref location,
2554                 ref value,
2555                 target,
2556                 unwind,
2557             } => DropAndReplace {
2558                 location: location.fold_with(folder),
2559                 value: value.fold_with(folder),
2560                 target,
2561                 unwind,
2562             },
2563             Yield {
2564                 ref value,
2565                 resume,
2566                 drop,
2567             } => Yield {
2568                 value: value.fold_with(folder),
2569                 resume: resume,
2570                 drop: drop,
2571             },
2572             Call {
2573                 ref func,
2574                 ref args,
2575                 ref destination,
2576                 cleanup,
2577             } => {
2578                 let dest = destination
2579                     .as_ref()
2580                     .map(|&(ref loc, dest)| (loc.fold_with(folder), dest));
2581
2582                 Call {
2583                     func: func.fold_with(folder),
2584                     args: args.fold_with(folder),
2585                     destination: dest,
2586                     cleanup,
2587                 }
2588             }
2589             Assert {
2590                 ref cond,
2591                 expected,
2592                 ref msg,
2593                 target,
2594                 cleanup,
2595             } => {
2596                 let msg = if let EvalErrorKind::BoundsCheck { ref len, ref index } = *msg {
2597                     EvalErrorKind::BoundsCheck {
2598                         len: len.fold_with(folder),
2599                         index: index.fold_with(folder),
2600                     }
2601                 } else {
2602                     msg.clone()
2603                 };
2604                 Assert {
2605                     cond: cond.fold_with(folder),
2606                     expected,
2607                     msg,
2608                     target,
2609                     cleanup,
2610                 }
2611             }
2612             GeneratorDrop => GeneratorDrop,
2613             Resume => Resume,
2614             Abort => Abort,
2615             Return => Return,
2616             Unreachable => Unreachable,
2617             FalseEdges {
2618                 real_target,
2619                 ref imaginary_targets,
2620             } => FalseEdges {
2621                 real_target,
2622                 imaginary_targets: imaginary_targets.clone(),
2623             },
2624             FalseUnwind {
2625                 real_target,
2626                 unwind,
2627             } => FalseUnwind {
2628                 real_target,
2629                 unwind,
2630             },
2631         };
2632         Terminator {
2633             source_info: self.source_info,
2634             kind,
2635         }
2636     }
2637
2638     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
2639         use mir::TerminatorKind::*;
2640
2641         match self.kind {
2642             SwitchInt {
2643                 ref discr,
2644                 switch_ty,
2645                 ..
2646             } => discr.visit_with(visitor) || switch_ty.visit_with(visitor),
2647             Drop { ref location, .. } => location.visit_with(visitor),
2648             DropAndReplace {
2649                 ref location,
2650                 ref value,
2651                 ..
2652             } => location.visit_with(visitor) || value.visit_with(visitor),
2653             Yield { ref value, .. } => value.visit_with(visitor),
2654             Call {
2655                 ref func,
2656                 ref args,
2657                 ref destination,
2658                 ..
2659             } => {
2660                 let dest = if let Some((ref loc, _)) = *destination {
2661                     loc.visit_with(visitor)
2662                 } else {
2663                     false
2664                 };
2665                 dest || func.visit_with(visitor) || args.visit_with(visitor)
2666             }
2667             Assert {
2668                 ref cond, ref msg, ..
2669             } => {
2670                 if cond.visit_with(visitor) {
2671                     if let EvalErrorKind::BoundsCheck { ref len, ref index } = *msg {
2672                         len.visit_with(visitor) || index.visit_with(visitor)
2673                     } else {
2674                         false
2675                     }
2676                 } else {
2677                     false
2678                 }
2679             }
2680             Goto { .. }
2681             | Resume
2682             | Abort
2683             | Return
2684             | GeneratorDrop
2685             | Unreachable
2686             | FalseEdges { .. }
2687             | FalseUnwind { .. } => false,
2688         }
2689     }
2690 }
2691
2692 impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> {
2693     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
2694         match self {
2695             &Place::Projection(ref p) => Place::Projection(p.fold_with(folder)),
2696             _ => self.clone(),
2697         }
2698     }
2699
2700     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
2701         if let &Place::Projection(ref p) = self {
2702             p.visit_with(visitor)
2703         } else {
2704             false
2705         }
2706     }
2707 }
2708
2709 impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
2710     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
2711         use mir::Rvalue::*;
2712         match *self {
2713             Use(ref op) => Use(op.fold_with(folder)),
2714             Repeat(ref op, len) => Repeat(op.fold_with(folder), len),
2715             Ref(region, bk, ref place) => {
2716                 Ref(region.fold_with(folder), bk, place.fold_with(folder))
2717             }
2718             Len(ref place) => Len(place.fold_with(folder)),
2719             Cast(kind, ref op, ty) => Cast(kind, op.fold_with(folder), ty.fold_with(folder)),
2720             BinaryOp(op, ref rhs, ref lhs) => {
2721                 BinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder))
2722             }
2723             CheckedBinaryOp(op, ref rhs, ref lhs) => {
2724                 CheckedBinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder))
2725             }
2726             UnaryOp(op, ref val) => UnaryOp(op, val.fold_with(folder)),
2727             Discriminant(ref place) => Discriminant(place.fold_with(folder)),
2728             NullaryOp(op, ty) => NullaryOp(op, ty.fold_with(folder)),
2729             Aggregate(ref kind, ref fields) => {
2730                 let kind = box match **kind {
2731                     AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)),
2732                     AggregateKind::Tuple => AggregateKind::Tuple,
2733                     AggregateKind::Adt(def, v, substs, n) => {
2734                         AggregateKind::Adt(def, v, substs.fold_with(folder), n)
2735                     }
2736                     AggregateKind::Closure(id, substs) => {
2737                         AggregateKind::Closure(id, substs.fold_with(folder))
2738                     }
2739                     AggregateKind::Generator(id, substs, movablity) => {
2740                         AggregateKind::Generator(id, substs.fold_with(folder), movablity)
2741                     }
2742                 };
2743                 Aggregate(kind, fields.fold_with(folder))
2744             }
2745         }
2746     }
2747
2748     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
2749         use mir::Rvalue::*;
2750         match *self {
2751             Use(ref op) => op.visit_with(visitor),
2752             Repeat(ref op, _) => op.visit_with(visitor),
2753             Ref(region, _, ref place) => region.visit_with(visitor) || place.visit_with(visitor),
2754             Len(ref place) => place.visit_with(visitor),
2755             Cast(_, ref op, ty) => op.visit_with(visitor) || ty.visit_with(visitor),
2756             BinaryOp(_, ref rhs, ref lhs) | CheckedBinaryOp(_, ref rhs, ref lhs) => {
2757                 rhs.visit_with(visitor) || lhs.visit_with(visitor)
2758             }
2759             UnaryOp(_, ref val) => val.visit_with(visitor),
2760             Discriminant(ref place) => place.visit_with(visitor),
2761             NullaryOp(_, ty) => ty.visit_with(visitor),
2762             Aggregate(ref kind, ref fields) => {
2763                 (match **kind {
2764                     AggregateKind::Array(ty) => ty.visit_with(visitor),
2765                     AggregateKind::Tuple => false,
2766                     AggregateKind::Adt(_, _, substs, _) => substs.visit_with(visitor),
2767                     AggregateKind::Closure(_, substs) => substs.visit_with(visitor),
2768                     AggregateKind::Generator(_, substs, _) => substs.visit_with(visitor),
2769                 }) || fields.visit_with(visitor)
2770             }
2771         }
2772     }
2773 }
2774
2775 impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> {
2776     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
2777         match *self {
2778             Operand::Copy(ref place) => Operand::Copy(place.fold_with(folder)),
2779             Operand::Move(ref place) => Operand::Move(place.fold_with(folder)),
2780             Operand::Constant(ref c) => Operand::Constant(c.fold_with(folder)),
2781         }
2782     }
2783
2784     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
2785         match *self {
2786             Operand::Copy(ref place) | Operand::Move(ref place) => place.visit_with(visitor),
2787             Operand::Constant(ref c) => c.visit_with(visitor),
2788         }
2789     }
2790 }
2791
2792 impl<'tcx, B, V, T> TypeFoldable<'tcx> for Projection<'tcx, B, V, T>
2793 where
2794     B: TypeFoldable<'tcx>,
2795     V: TypeFoldable<'tcx>,
2796     T: TypeFoldable<'tcx>,
2797 {
2798     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
2799         use mir::ProjectionElem::*;
2800
2801         let base = self.base.fold_with(folder);
2802         let elem = match self.elem {
2803             Deref => Deref,
2804             Field(f, ref ty) => Field(f, ty.fold_with(folder)),
2805             Index(ref v) => Index(v.fold_with(folder)),
2806             ref elem => elem.clone(),
2807         };
2808
2809         Projection { base, elem }
2810     }
2811
2812     fn super_visit_with<Vs: TypeVisitor<'tcx>>(&self, visitor: &mut Vs) -> bool {
2813         use mir::ProjectionElem::*;
2814
2815         self.base.visit_with(visitor) || match self.elem {
2816             Field(_, ref ty) => ty.visit_with(visitor),
2817             Index(ref v) => v.visit_with(visitor),
2818             _ => false,
2819         }
2820     }
2821 }
2822
2823 impl<'tcx> TypeFoldable<'tcx> for Field {
2824     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, _: &mut F) -> Self {
2825         *self
2826     }
2827     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> bool {
2828         false
2829     }
2830 }
2831
2832 impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> {
2833     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
2834         Constant {
2835             span: self.span.clone(),
2836             ty: self.ty.fold_with(folder),
2837             literal: self.literal.fold_with(folder),
2838         }
2839     }
2840     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
2841         self.ty.visit_with(visitor) || self.literal.visit_with(visitor)
2842     }
2843 }
2844
2845 impl<'tcx> TypeFoldable<'tcx> for Literal<'tcx> {
2846     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
2847         match *self {
2848             Literal::Value { value } => Literal::Value {
2849                 value: value.fold_with(folder),
2850             },
2851             Literal::Promoted { index } => Literal::Promoted { index },
2852         }
2853     }
2854     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
2855         match *self {
2856             Literal::Value { value } => value.visit_with(visitor),
2857             Literal::Promoted { .. } => false,
2858         }
2859     }
2860 }