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