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