mod.rs 89.9 KB
Newer Older
N
Niko Matsakis 已提交
1 2 3 4 5 6 7 8 9 10
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

11
//! MIR datatypes and passes. See the [rustc guide] for more info.
M
Malo Jaffré 已提交
12
//!
13
//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir.html
14

15
use graphviz::IntoCow;
16
use middle::region;
17
use rustc_data_structures::sync::{Lrc};
18
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
19 20 21
use rustc_data_structures::control_flow_graph::dominators::{Dominators, dominators};
use rustc_data_structures::control_flow_graph::{GraphPredecessors, GraphSuccessors};
use rustc_data_structures::control_flow_graph::ControlFlowGraph;
22
use rustc_data_structures::small_vec::SmallVec;
23
use rustc_serialize as serialize;
24
use hir::def::CtorKind;
25
use hir::def_id::DefId;
26
use mir::visit::MirVisitable;
O
Oliver Schneider 已提交
27
use mir::interpret::{Value, Scalar, EvalErrorKind};
A
Ariel Ben-Yehuda 已提交
28
use ty::subst::{Subst, Substs};
29
use ty::{self, AdtDef, CanonicalTy, ClosureSubsts, GeneratorSubsts, Region, Ty, TyCtxt};
30
use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
31
use util::ppaux;
O
Oliver Schneider 已提交
32
use std::slice;
33
use hir::{self, InlineAsm};
34
use std::borrow::{Cow};
35
use rustc_data_structures::sync::ReadGuard;
36
use std::fmt::{self, Debug, Formatter, Write};
37
use std::{iter, mem, option, u32};
38
use std::ops::{Index, IndexMut};
39
use std::vec::IntoIter;
40
use syntax::ast::{self, Name};
O
Oliver Schneider 已提交
41
use syntax::symbol::InternedString;
42
use syntax_pos::{Span, DUMMY_SP};
O
Oliver Schneider 已提交
43 44
use rustc_apfloat::ieee::{Single, Double};
use rustc_apfloat::Float;
N
Niko Matsakis 已提交
45

46 47
pub use mir::interpret::AssertMessage;

E
Eduard Burtescu 已提交
48 49 50 51
mod cache;
pub mod tcx;
pub mod visit;
pub mod traversal;
52
pub mod interpret;
53
pub mod mono;
54

55 56 57
/// Types for locals
type LocalDecls<'tcx> = IndexVec<Local, LocalDecl<'tcx>>;

58 59
pub trait HasLocalDecls<'tcx> {
    fn local_decls(&self) -> &LocalDecls<'tcx>;
60 61
}

62 63
impl<'tcx> HasLocalDecls<'tcx> for LocalDecls<'tcx> {
    fn local_decls(&self) -> &LocalDecls<'tcx> {
64 65 66 67
        self
    }
}

68 69
impl<'tcx> HasLocalDecls<'tcx> for Mir<'tcx> {
    fn local_decls(&self) -> &LocalDecls<'tcx> {
70 71 72 73
        &self.local_decls
    }
}

N
Niko Matsakis 已提交
74
/// Lowered representation of a single function.
75
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
76
pub struct Mir<'tcx> {
N
Niko Matsakis 已提交
77 78
    /// List of basic blocks. References to basic block use a newtyped index type `BasicBlock`
    /// that indexes into this vector.
79
    basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
N
Niko Matsakis 已提交
80

81 82 83
    /// List of source scopes; these are referenced by statements
    /// and used for debuginfo. Indexed by a `SourceScope`.
    pub source_scopes: IndexVec<SourceScope, SourceScopeData>,
N
Niko Matsakis 已提交
84

85
    /// Crate-local information for each source scope, that can't (and
86
    /// needn't) be tracked across crates.
87
    pub source_scope_local_data: ClearCrossCrate<IndexVec<SourceScope, SourceScopeLocalData>>,
88

89 90
    /// Rvalues promoted from this function, such as borrows of constants.
    /// Each of them is the Mir of a constant with the fn's type parameters
91
    /// in scope, but a separate set of locals.
92
    pub promoted: IndexVec<Promoted, Mir<'tcx>>,
93

J
John Kåre Alsaker 已提交
94 95
    /// Yield type of the function, if it is a generator.
    pub yield_ty: Option<Ty<'tcx>>,
J
John Kåre Alsaker 已提交
96 97 98 99 100 101 102

    /// Generator drop glue
    pub generator_drop: Option<Box<Mir<'tcx>>>,

    /// The layout of a generator. Produced by the state transformation.
    pub generator_layout: Option<GeneratorLayout<'tcx>>,

103 104 105 106 107
    /// Declarations of locals.
    ///
    /// The first local is the return value pointer, followed by `arg_count`
    /// locals for the function arguments, followed by any user-declared
    /// variables and temporaries.
108
    pub local_decls: LocalDecls<'tcx>,
N
Niko Matsakis 已提交
109

110 111
    /// Number of arguments this function takes.
    ///
112
    /// Starting at local 1, `arg_count` locals will be provided by the caller
113 114 115 116
    /// and can be assumed to be initialized.
    ///
    /// If this MIR was built for a constant, this will be 0.
    pub arg_count: usize,
A
Ariel Ben-Yehuda 已提交
117

118 119 120 121
    /// Names and capture modes of all the closure upvars, assuming
    /// the first argument is either the closure or a reference to it.
    pub upvar_decls: Vec<UpvarDecl>,

122 123
    /// Mark an argument local (which must be a tuple) as getting passed as
    /// its individual components at the LLVM level.
124 125
    ///
    /// This is used for the "rust-call" ABI.
126
    pub spread_arg: Option<Local>,
127

A
Ariel Ben-Yehuda 已提交
128 129
    /// A span representing this MIR, for error reporting
    pub span: Span,
130 131

    /// A cache for various calculations
E
Eduard Burtescu 已提交
132
    cache: cache::Cache
N
Niko Matsakis 已提交
133 134 135 136 137
}

/// where execution begins
pub const START_BLOCK: BasicBlock = BasicBlock(0);

138
impl<'tcx> Mir<'tcx> {
139
    pub fn new(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
140
               source_scopes: IndexVec<SourceScope, SourceScopeData>,
141 142
               source_scope_local_data: ClearCrossCrate<IndexVec<SourceScope,
                                                                 SourceScopeLocalData>>,
143
               promoted: IndexVec<Promoted, Mir<'tcx>>,
J
John Kåre Alsaker 已提交
144
               yield_ty: Option<Ty<'tcx>>,
145 146
               local_decls: IndexVec<Local, LocalDecl<'tcx>>,
               arg_count: usize,
147 148 149
               upvar_decls: Vec<UpvarDecl>,
               span: Span) -> Self
    {
O
Oliver Schneider 已提交
150
        // We need `arg_count` locals, and one for the return place
151 152 153
        assert!(local_decls.len() >= arg_count + 1,
            "expected at least {} locals, got {}", arg_count + 1, local_decls.len());

154
        Mir {
155
            basic_blocks,
156
            source_scopes,
157
            source_scope_local_data,
158
            promoted,
J
John Kåre Alsaker 已提交
159
            yield_ty,
J
John Kåre Alsaker 已提交
160 161
            generator_drop: None,
            generator_layout: None,
162 163 164
            local_decls,
            arg_count,
            upvar_decls,
165
            spread_arg: None,
166
            span,
E
Eduard Burtescu 已提交
167
            cache: cache::Cache::new()
168
        }
N
Niko Matsakis 已提交
169 170
    }

171 172 173
    #[inline]
    pub fn basic_blocks(&self) -> &IndexVec<BasicBlock, BasicBlockData<'tcx>> {
        &self.basic_blocks
N
Niko Matsakis 已提交
174 175
    }

176 177
    #[inline]
    pub fn basic_blocks_mut(&mut self) -> &mut IndexVec<BasicBlock, BasicBlockData<'tcx>> {
178
        self.cache.invalidate();
179
        &mut self.basic_blocks
N
Niko Matsakis 已提交
180
    }
181

O
Oliver Schneider 已提交
182 183 184 185 186 187 188 189 190
    #[inline]
    pub fn basic_blocks_and_local_decls_mut(&mut self) -> (
        &mut IndexVec<BasicBlock, BasicBlockData<'tcx>>,
        &mut LocalDecls<'tcx>,
    ) {
        self.cache.invalidate();
        (&mut self.basic_blocks, &mut self.local_decls)
    }

191
    #[inline]
192
    pub fn predecessors(&self) -> ReadGuard<IndexVec<BasicBlock, Vec<BasicBlock>>> {
193 194 195 196
        self.cache.predecessors(self)
    }

    #[inline]
197 198
    pub fn predecessors_for(&self, bb: BasicBlock) -> ReadGuard<Vec<BasicBlock>> {
        ReadGuard::map(self.predecessors(), |p| &p[bb])
199
    }
200

201 202 203 204 205
    #[inline]
    pub fn dominators(&self) -> Dominators<BasicBlock> {
        dominators(self)
    }

206 207 208 209 210
    #[inline]
    pub fn local_kind(&self, local: Local) -> LocalKind {
        let index = local.0 as usize;
        if index == 0 {
            debug_assert!(self.local_decls[local].mutability == Mutability::Mut,
O
Oliver Schneider 已提交
211
                          "return place should be mutable");
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227

            LocalKind::ReturnPointer
        } else if index < self.arg_count + 1 {
            LocalKind::Arg
        } else if self.local_decls[local].name.is_some() {
            LocalKind::Var
        } else {
            debug_assert!(self.local_decls[local].mutability == Mutability::Mut,
                          "temp should be mutable");

            LocalKind::Temp
        }
    }

    /// Returns an iterator over all temporaries.
    #[inline]
228
    pub fn temps_iter<'a>(&'a self) -> impl Iterator<Item=Local> + 'a {
229 230
        (self.arg_count+1..self.local_decls.len()).filter_map(move |index| {
            let local = Local::new(index);
231
            if self.local_decls[local].is_user_variable {
232
                None
233 234
            } else {
                Some(local)
235
            }
236 237 238 239 240
        })
    }

    /// Returns an iterator over all user-declared locals.
    #[inline]
241
    pub fn vars_iter<'a>(&'a self) -> impl Iterator<Item=Local> + 'a {
242 243
        (self.arg_count+1..self.local_decls.len()).filter_map(move |index| {
            let local = Local::new(index);
244
            if self.local_decls[local].is_user_variable {
245
                Some(local)
246 247
            } else {
                None
248
            }
249 250 251
        })
    }

252
    /// Returns an iterator over all user-declared mutable arguments and locals.
253
    #[inline]
254 255
    pub fn mut_vars_and_args_iter<'a>(&'a self) -> impl Iterator<Item=Local> + 'a {
        (1..self.local_decls.len()).filter_map(move |index| {
256 257
            let local = Local::new(index);
            let decl = &self.local_decls[local];
258 259 260
            if (decl.is_user_variable || index < self.arg_count + 1)
               && decl.mutability == Mutability::Mut
            {
261 262 263 264 265 266 267
                Some(local)
            } else {
                None
            }
        })
    }

268 269
    /// Returns an iterator over all function arguments.
    #[inline]
270 271 272
    pub fn args_iter(&self) -> impl Iterator<Item=Local> {
        let arg_count = self.arg_count;
        (1..arg_count+1).map(Local::new)
273 274 275
    }

    /// Returns an iterator over all user-defined variables and compiler-generated temporaries (all
O
Oliver Schneider 已提交
276
    /// locals that are neither arguments nor the return place).
277
    #[inline]
J
Jonas Schievink 已提交
278 279 280 281
    pub fn vars_and_temps_iter(&self) -> impl Iterator<Item=Local> {
        let arg_count = self.arg_count;
        let local_count = self.local_decls.len();
        (arg_count+1..local_count).map(Local::new)
282 283
    }

284 285 286 287 288 289 290
    /// Changes a statement to a nop. This is both faster than deleting instructions and avoids
    /// invalidating statement indices in `Location`s.
    pub fn make_statement_nop(&mut self, location: Location) {
        let block = &mut self[location.block];
        debug_assert!(location.statement_index < block.statements.len());
        block.statements[location.statement_index].make_nop()
    }
O
Oliver Schneider 已提交
291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308

    /// Returns the source info associated with `location`.
    pub fn source_info(&self, location: Location) -> &SourceInfo {
        let block = &self[location.block];
        let stmts = &block.statements;
        let idx = location.statement_index;
        if idx < stmts.len() {
            &stmts[idx].source_info
        } else {
            assert!(idx == stmts.len());
            &block.terminator().source_info
        }
    }

    /// Return the return type, it always return first element from `local_decls` array
    pub fn return_ty(&self) -> Ty<'tcx> {
        self.local_decls[RETURN_PLACE].ty
    }
N
Niko Matsakis 已提交
309 310
}

O
Oliver Schneider 已提交
311
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
A
Ariel Ben-Yehuda 已提交
312 313 314 315 316 317 318 319
pub enum Safety {
    Safe,
    /// Unsafe because of a PushUnsafeBlock
    BuiltinUnsafe,
    /// Unsafe because of an unsafe fn
    FnUnsafe,
    /// Unsafe because of an `unsafe` block
    ExplicitUnsafe(ast::NodeId)
320 321
}

322 323
impl_stable_hash_for!(struct Mir<'tcx> {
    basic_blocks,
324
    source_scopes,
325
    source_scope_local_data,
326
    promoted,
J
John Kåre Alsaker 已提交
327
    yield_ty,
J
John Kåre Alsaker 已提交
328 329
    generator_drop,
    generator_layout,
330 331 332 333 334 335 336 337
    local_decls,
    arg_count,
    upvar_decls,
    spread_arg,
    span,
    cache
});

338 339 340 341 342
impl<'tcx> Index<BasicBlock> for Mir<'tcx> {
    type Output = BasicBlockData<'tcx>;

    #[inline]
    fn index(&self, index: BasicBlock) -> &BasicBlockData<'tcx> {
343
        &self.basic_blocks()[index]
344 345 346 347 348 349
    }
}

impl<'tcx> IndexMut<BasicBlock> for Mir<'tcx> {
    #[inline]
    fn index_mut(&mut self, index: BasicBlock) -> &mut BasicBlockData<'tcx> {
350
        &mut self.basic_blocks_mut()[index]
351 352 353
    }
}

354
#[derive(Clone, Debug)]
O
Oliver Schneider 已提交
355
pub enum ClearCrossCrate<T> {
356 357 358 359
    Clear,
    Set(T)
}

O
Oliver Schneider 已提交
360 361
impl<T: serialize::Encodable> serialize::UseSpecializedEncodable for ClearCrossCrate<T> {}
impl<T: serialize::Decodable> serialize::UseSpecializedDecodable for ClearCrossCrate<T> {}
362

363 364 365
/// Grouped information about the source code origin of a MIR entity.
/// Intended to be inspected by diagnostics and debuginfo.
/// Most passes can work with it as a whole, within a single function.
A
Ariel Ben-Yehuda 已提交
366
#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
367 368 369 370
pub struct SourceInfo {
    /// Source span for the AST pertaining to this MIR entity.
    pub span: Span,

371 372 373
    /// The source scope, keeping track of which bindings can be
    /// seen by debuginfo, active lint levels, `unsafe {...}`, etc.
    pub scope: SourceScope
374 375
}

N
Niko Matsakis 已提交
376 377 378
///////////////////////////////////////////////////////////////////////////
// Mutability and borrow kinds

379
#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
N
Niko Matsakis 已提交
380 381 382 383 384
pub enum Mutability {
    Mut,
    Not,
}

385
#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
N
Niko Matsakis 已提交
386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427
pub enum BorrowKind {
    /// Data must be immutable and is aliasable.
    Shared,

    /// Data must be immutable but not aliasable.  This kind of borrow
    /// cannot currently be expressed by the user and is used only in
    /// implicit closure bindings. It is needed when you the closure
    /// is borrowing or mutating a mutable referent, e.g.:
    ///
    ///    let x: &mut isize = ...;
    ///    let y = || *x += 5;
    ///
    /// If we were to try to translate this closure into a more explicit
    /// form, we'd encounter an error with the code as written:
    ///
    ///    struct Env { x: & &mut isize }
    ///    let x: &mut isize = ...;
    ///    let y = (&mut Env { &x }, fn_ptr);  // Closure is pair of env and fn
    ///    fn fn_ptr(env: &mut Env) { **env.x += 5; }
    ///
    /// This is then illegal because you cannot mutate a `&mut` found
    /// in an aliasable location. To solve, you'd have to translate with
    /// an `&mut` borrow:
    ///
    ///    struct Env { x: & &mut isize }
    ///    let x: &mut isize = ...;
    ///    let y = (&mut Env { &mut x }, fn_ptr); // changed from &x to &mut x
    ///    fn fn_ptr(env: &mut Env) { **env.x += 5; }
    ///
    /// Now the assignment to `**env.x` is legal, but creating a
    /// mutable pointer to `x` is not because `x` is not mutable. We
    /// could fix this by declaring `x` as `let mut x`. This is ok in
    /// user code, if awkward, but extra weird for closures, since the
    /// borrow is hidden.
    ///
    /// So we introduce a "unique imm" borrow -- the referent is
    /// immutable, but not aliasable. This solves the problem. For
    /// simplicity, we don't give users the way to express this
    /// borrow, it's just used when translating closures.
    Unique,

    /// Data is mutable and not aliasable.
428 429 430 431 432
    Mut {
        /// True if this borrow arose from method-call auto-ref
        /// (i.e. `adjustment::Adjust::Borrow`)
        allow_two_phase_borrow: bool
    }
N
Niko Matsakis 已提交
433 434
}

435 436 437 438 439 440 441 442 443
impl BorrowKind {
    pub fn allows_two_phase_borrow(&self) -> bool {
        match *self {
            BorrowKind::Shared | BorrowKind::Unique => false,
            BorrowKind::Mut { allow_two_phase_borrow } => allow_two_phase_borrow,
        }
    }
}

N
Niko Matsakis 已提交
444 445 446
///////////////////////////////////////////////////////////////////////////
// Variables and temps

O
Oliver Schneider 已提交
447 448 449 450 451
newtype_index!(Local
    {
        DEBUG_FORMAT = "_{}",
        const RETURN_PLACE = 0,
    });
452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468

/// Classifies locals into categories. See `Mir::local_kind`.
#[derive(PartialEq, Eq, Debug)]
pub enum LocalKind {
    /// User-declared variable binding
    Var,
    /// Compiler-introduced temporary
    Temp,
    /// Function argument
    Arg,
    /// Location of function's return value
    ReturnPointer,
}

/// A MIR local.
///
/// This can be a binding declared by the user, a temporary inserted by the compiler, a function
O
Oliver Schneider 已提交
469
/// argument, or the return place.
A
Ariel Ben-Yehuda 已提交
470
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
471 472 473
pub struct LocalDecl<'tcx> {
    /// `let mut x` vs `let x`.
    ///
O
Oliver Schneider 已提交
474
    /// Temporaries and the return place are always mutable.
N
Niko Matsakis 已提交
475
    pub mutability: Mutability,
476

477 478 479
    /// True if this corresponds to a user-declared local variable.
    pub is_user_variable: bool,

480 481
    /// True if this is an internal local
    ///
J
John Kåre Alsaker 已提交
482
    /// These locals are not based on types in the source code and are only used
A
Ariel Ben-Yehuda 已提交
483
    /// for a few desugarings at the moment.
484 485 486 487 488
    ///
    /// The generator transformation will sanity check the locals which are live
    /// across a suspension point against the type components of the generator
    /// which type checking knows are live across a suspension point. We need to
    /// flag drop flags to avoid triggering this check as they are introduced
J
John Kåre Alsaker 已提交
489
    /// after typeck.
490
    ///
A
Ariel Ben-Yehuda 已提交
491 492 493
    /// Unsafety checking will also ignore dereferences of these locals,
    /// so they can be used for raw pointers only used in a desugaring.
    ///
494 495 496
    /// This should be sound because the drop flags are fully algebraic, and
    /// therefore don't affect the OIBIT or outlives properties of the
    /// generator.
497 498
    pub internal: bool,

499
    /// Type of this local.
500
    pub ty: Ty<'tcx>,
501

502 503 504 505 506
    /// Name of the local, used in debuginfo and pretty-printing.
    ///
    /// Note that function arguments can also have this set to `Some(_)`
    /// to generate better debuginfo.
    pub name: Option<Name>,
N
Niko Matsakis 已提交
507

508
    /// The *syntactic* (i.e. not visibility) source scope the local is defined
509 510
    /// in. If the local was defined in a let-statement, this
    /// is *within* the let-statement, rather than outside
A
Ariel Ben-Yehuda 已提交
511
    /// of it.
512
    ///
513 514
    /// This is needed because the visibility source scope of locals within
    /// a let-statement is weird.
515 516 517 518 519 520 521
    ///
    /// The reason is that we want the local to be *within* the let-statement
    /// for lint purposes, but we want the local to be *after* the let-statement
    /// for names-in-scope purposes.
    ///
    /// That's it, if we have a let-statement like the one in this
    /// function:
522
    ///
523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558
    /// ```
    /// fn foo(x: &str) {
    ///     #[allow(unused_mut)]
    ///     let mut x: u32 = { // <- one unused mut
    ///         let mut y: u32 = x.parse().unwrap();
    ///         y + 2
    ///     };
    ///     drop(x);
    /// }
    /// ```
    ///
    /// Then, from a lint point of view, the declaration of `x: u32`
    /// (and `y: u32`) are within the `#[allow(unused_mut)]` scope - the
    /// lint scopes are the same as the AST/HIR nesting.
    ///
    /// However, from a name lookup point of view, the scopes look more like
    /// as if the let-statements were `match` expressions:
    ///
    /// ```
    /// fn foo(x: &str) {
    ///     match {
    ///         match x.parse().unwrap() {
    ///             y => y + 2
    ///         }
    ///     } {
    ///         x => drop(x)
    ///     };
    /// }
    /// ```
    ///
    /// We care about the name-lookup scopes for debuginfo - if the
    /// debuginfo instruction pointer is at the call to `x.parse()`, we
    /// want `x` to refer to `x: &str`, but if it is at the call to
    /// `drop(x)`, we want it to refer to `x: u32`.
    ///
    /// To allow both uses to work, we need to have more than a single scope
559
    /// for a local. We have the `syntactic_source_info.scope` represent the
560
    /// "syntactic" lint scope (with a variable being under its let
561
    /// block) while the `visibility_source_info.scope` represents the "local variable"
562 563 564 565
    /// scope (where the "rest" of a block is under all prior let-statements).
    ///
    /// The end result looks like this:
    ///
566
    /// ```text
567 568 569 570 571 572
    /// ROOT SCOPE
    ///  │{ argument x: &str }
    ///  │
    ///  │ │{ #[allow(unused_mut] } // this is actually split into 2 scopes
    ///  │ │                        // in practice because I'm lazy.
    ///  │ │
573
    ///  │ │← x.syntactic_source_info.scope
574 575
    ///  │ │← `x.parse().unwrap()`
    ///  │ │
576
    ///  │ │ │← y.syntactic_source_info.scope
577 578 579
    ///  │ │
    ///  │ │ │{ let y: u32 }
    ///  │ │ │
580
    ///  │ │ │← y.visibility_source_info.scope
581 582 583
    ///  │ │ │← `y + 2`
    ///  │
    ///  │ │{ let x: u32 }
584
    ///  │ │← x.visibility_source_info.scope
585
    ///  │ │← `drop(x)` // this accesses `x: u32`
586
    /// ```
587
    pub syntactic_source_info: SourceInfo,
588 589 590 591

    /// Source info of the local. The `SourceScope` is the *visibility* one,
    /// not the the *syntactic* one (see `syntactic_source_info` for more details).
    pub visibility_source_info: SourceInfo,
N
Niko Matsakis 已提交
592 593
}

594 595 596
impl<'tcx> LocalDecl<'tcx> {
    /// Create a new `LocalDecl` for a temporary.
    #[inline]
597
    pub fn new_temp(ty: Ty<'tcx>, span: Span) -> Self {
598 599
        LocalDecl {
            mutability: Mutability::Mut,
600
            ty,
601
            name: None,
602
            syntactic_source_info: SourceInfo {
603
                span,
604
                scope: OUTERMOST_SOURCE_SCOPE
605
            },
606
            visibility_source_info: SourceInfo {
607 608 609
                span,
                scope: OUTERMOST_SOURCE_SCOPE
            },
610 611 612 613 614 615 616 617 618 619 620 621
            internal: false,
            is_user_variable: false
        }
    }

    /// Create a new `LocalDecl` for a internal temporary.
    #[inline]
    pub fn new_internal(ty: Ty<'tcx>, span: Span) -> Self {
        LocalDecl {
            mutability: Mutability::Mut,
            ty,
            name: None,
622
            syntactic_source_info: SourceInfo {
623
                span,
624
                scope: OUTERMOST_SOURCE_SCOPE
625
            },
626
            visibility_source_info: SourceInfo {
627 628 629
                span,
                scope: OUTERMOST_SOURCE_SCOPE
            },
630
            internal: true,
631
            is_user_variable: false
632 633
        }
    }
634

O
Oliver Schneider 已提交
635
    /// Builds a `LocalDecl` for the return place.
636 637 638
    ///
    /// This must be inserted into the `local_decls` list as the first local.
    #[inline]
O
Oliver Schneider 已提交
639
    pub fn new_return_place(return_ty: Ty, span: Span) -> LocalDecl {
640 641 642
        LocalDecl {
            mutability: Mutability::Mut,
            ty: return_ty,
643
            syntactic_source_info: SourceInfo {
644
                span,
645
                scope: OUTERMOST_SOURCE_SCOPE
646
            },
647
            visibility_source_info: SourceInfo {
648 649 650
                span,
                scope: OUTERMOST_SOURCE_SCOPE
            },
651
            internal: false,
652
            name: None,     // FIXME maybe we do want some name here?
653
            is_user_variable: false
654 655
        }
    }
656 657 658 659 660 661 662 663
}

/// A closure capture, with its name and mode.
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct UpvarDecl {
    pub debug_name: Name,

    /// If true, the capture is behind a reference.
O
Oliver Schneider 已提交
664 665 666
    pub by_ref: bool,

    pub mutability: Mutability,
N
Niko Matsakis 已提交
667 668 669 670 671
}

///////////////////////////////////////////////////////////////////////////
// BasicBlock

O
Oliver Schneider 已提交
672 673 674 675 676 677 678 679 680 681
newtype_index!(BasicBlock { DEBUG_FORMAT = "bb{}" });

impl BasicBlock {
    pub fn start_location(self) -> Location {
        Location {
            block: self,
            statement_index: 0,
        }
    }
}
N
Niko Matsakis 已提交
682 683

///////////////////////////////////////////////////////////////////////////
S
Simonas Kazlauskas 已提交
684
// BasicBlockData and Terminator
N
Niko Matsakis 已提交
685

686
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
687
pub struct BasicBlockData<'tcx> {
N
Niko Matsakis 已提交
688
    /// List of statements in this block.
689
    pub statements: Vec<Statement<'tcx>>,
N
Niko Matsakis 已提交
690 691 692 693 694 695 696 697 698

    /// Terminator for this block.
    ///
    /// NB. This should generally ONLY be `None` during construction.
    /// Therefore, you should generally access it via the
    /// `terminator()` or `terminator_mut()` methods. The only
    /// exception is that certain passes, such as `simplify_cfg`, swap
    /// out the terminator temporarily with `None` while they continue
    /// to recurse over the set of basic blocks.
S
Simonas Kazlauskas 已提交
699
    pub terminator: Option<Terminator<'tcx>>,
N
Niko Matsakis 已提交
700 701

    /// If true, this block lies on an unwind path. This is used
I
Irina Popa 已提交
702
    /// during codegen where distinct kinds of basic blocks may be
N
Niko Matsakis 已提交
703 704
    /// generated (particularly for MSVC cleanup). Unwind blocks must
    /// only branch to other unwind blocks.
705
    pub is_cleanup: bool,
N
Niko Matsakis 已提交
706 707
}

708 709
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct Terminator<'tcx> {
710
    pub source_info: SourceInfo,
711 712 713
    pub kind: TerminatorKind<'tcx>
}

714
#[derive(Clone, RustcEncodable, RustcDecodable)]
715
pub enum TerminatorKind<'tcx> {
N
Niko Matsakis 已提交
716
    /// block should have one successor in the graph; we jump there
717 718 719
    Goto {
        target: BasicBlock,
    },
N
Niko Matsakis 已提交
720

721 722 723 724
    /// operand evaluates to an integer; jump depending on its value
    /// to one of the targets, and otherwise fallback to `otherwise`
    SwitchInt {
        /// discriminant value being tested
725
        discr: Operand<'tcx>,
726 727 728 729 730 731

        /// type of value being tested
        switch_ty: Ty<'tcx>,

        /// Possible values. The locations to branch to in each case
        /// are found in the corresponding indices from the `targets` vector.
O
Oliver Schneider 已提交
732
        values: Cow<'tcx, [u128]>,
733

734
        /// Possible branch sites. The last element of this vector is used
735
        /// for the otherwise branch, so targets.len() == values.len() + 1
736 737 738 739 740 741 742 743 744
        /// should hold.
        // This invariant is quite non-obvious and also could be improved.
        // One way to make this invariant is to have something like this instead:
        //
        // branches: Vec<(ConstInt, BasicBlock)>,
        // otherwise: Option<BasicBlock> // exhaustive if None
        //
        // However we’ve decided to keep this as-is until we figure a case
        // where some other approach seems to be strictly better than other.
745 746 747
        targets: Vec<BasicBlock>,
    },

748 749 750 751
    /// Indicates that the landing pad is finished and unwinding should
    /// continue. Emitted by build::scope::diverge_cleanup.
    Resume,

D
David Henningsson 已提交
752 753 754 755
    /// Indicates that the landing pad is finished and that the process
    /// should abort. Used to prevent unwinding for foreign items.
    Abort,

O
Oliver Schneider 已提交
756 757
    /// Indicates a normal return. The return place should have
    /// been filled in by now. This should occur at most once.
N
Niko Matsakis 已提交
758 759
    Return,

760 761 762
    /// Indicates a terminator that can never be reached.
    Unreachable,

O
Oliver Schneider 已提交
763
    /// Drop the Place
764
    Drop {
O
Oliver Schneider 已提交
765
        location: Place<'tcx>,
766 767 768 769
        target: BasicBlock,
        unwind: Option<BasicBlock>
    },

O
Oliver Schneider 已提交
770
    /// Drop the Place and assign the new value over it. This ensures
771
    /// that the assignment to `P` occurs *even if* the destructor for
O
Oliver Schneider 已提交
772 773 774 775 776
    /// place unwinds. Its semantics are best explained by by the
    /// elaboration:
    ///
    /// ```
    /// BB0 {
777
    ///   DropAndReplace(P <- V, goto BB1, unwind BB2)
O
Oliver Schneider 已提交
778 779 780 781 782 783 784
    /// }
    /// ```
    ///
    /// becomes
    ///
    /// ```
    /// BB0 {
785
    ///   Drop(P, goto BB1, unwind BB2)
O
Oliver Schneider 已提交
786 787
    /// }
    /// BB1 {
788 789
    ///   // P is now unitialized
    ///   P <- V
O
Oliver Schneider 已提交
790 791
    /// }
    /// BB2 {
792 793
    ///   // P is now unitialized -- its dtor panicked
    ///   P <- V
O
Oliver Schneider 已提交
794 795
    /// }
    /// ```
796
    DropAndReplace {
O
Oliver Schneider 已提交
797
        location: Place<'tcx>,
798 799 800 801 802
        value: Operand<'tcx>,
        target: BasicBlock,
        unwind: Option<BasicBlock>,
    },

803
    /// Block ends with a call of a converging function
804
    Call {
805 806
        /// The function that’s being called
        func: Operand<'tcx>,
O
Oliver Schneider 已提交
807 808 809 810
        /// Arguments the function is called with.
        /// These are owned by the callee, which is free to modify them.
        /// This allows the memory occupied by "by-value" arguments to be
        /// reused across function calls without duplicating the contents.
811
        args: Vec<Operand<'tcx>>,
S
Simonas Kazlauskas 已提交
812
        /// Destination for the return value. If some, the call is converging.
O
Oliver Schneider 已提交
813
        destination: Option<(Place<'tcx>, BasicBlock)>,
S
Simonas Kazlauskas 已提交
814 815
        /// Cleanups to be done if the call unwinds.
        cleanup: Option<BasicBlock>
816
    },
817 818 819 820 821 822 823 824 825

    /// Jump to the target if the condition has the expected value,
    /// otherwise panic with a message and a cleanup target.
    Assert {
        cond: Operand<'tcx>,
        expected: bool,
        msg: AssertMessage<'tcx>,
        target: BasicBlock,
        cleanup: Option<BasicBlock>
J
John Kåre Alsaker 已提交
826 827 828
    },

    /// A suspend point
J
John Kåre Alsaker 已提交
829
    Yield {
J
John Kåre Alsaker 已提交
830 831 832 833 834 835 836 837 838 839
        /// The value to return
        value: Operand<'tcx>,
        /// Where to resume to
        resume: BasicBlock,
        /// Cleanup to be done if the generator is dropped at this suspend point
        drop: Option<BasicBlock>,
    },

    /// Indicates the end of the dropping of a generator
    GeneratorDrop,
O
Oliver Schneider 已提交
840

841 842
    /// A block where control flow only ever takes one real path, but borrowck
    /// needs to be more conservative.
O
Oliver Schneider 已提交
843
    FalseEdges {
844
        /// The target normal control flow will take
O
Oliver Schneider 已提交
845
        real_target: BasicBlock,
846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862
        /// The list of blocks control flow could conceptually take, but won't
        /// in practice
        imaginary_targets: Vec<BasicBlock>,
    },
    /// A terminator for blocks that only take one path in reality, but where we
    /// reserve the right to unwind in borrowck, even if it won't happen in practice.
    /// This can arise in infinite loops with no function calls for example.
    FalseUnwind {
        /// The target normal control flow will take
        real_target: BasicBlock,
        /// The imaginary cleanup block link. This particular path will never be taken
        /// in practice, but in order to avoid fragility we want to always
        /// consider it in borrowck. We don't want to accept programs which
        /// pass borrowck only when panic=abort or some assertions are disabled
        /// due to release vs. debug mode builds. This needs to be an Option because
        /// of the remove_noop_landing_pads and no_landing_pads passes
        unwind: Option<BasicBlock>,
O
Oliver Schneider 已提交
863
    },
864 865
}

866 867 868 869 870
pub type Successors<'a> =
    iter::Chain<option::IntoIter<&'a BasicBlock>, slice::Iter<'a, BasicBlock>>;
pub type SuccessorsMut<'a> =
    iter::Chain<option::IntoIter<&'a mut BasicBlock>, slice::IterMut<'a, BasicBlock>>;

871
impl<'tcx> Terminator<'tcx> {
872
    pub fn successors(&self) -> Successors {
873 874 875
        self.kind.successors()
    }

876
    pub fn successors_mut(&mut self) -> SuccessorsMut {
877 878
        self.kind.successors_mut()
    }
O
Oliver Schneider 已提交
879 880 881 882

    pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> {
        self.kind.unwind_mut()
    }
883 884 885
}

impl<'tcx> TerminatorKind<'tcx> {
D
Douglas Campos 已提交
886
    pub fn if_<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, cond: Operand<'tcx>,
887
                         t: BasicBlock, f: BasicBlock) -> TerminatorKind<'tcx> {
O
Oliver Schneider 已提交
888
        static BOOL_SWITCH_FALSE: &'static [u128] = &[0];
889 890 891 892 893 894 895 896
        TerminatorKind::SwitchInt {
            discr: cond,
            switch_ty: tcx.types.bool,
            values: From::from(BOOL_SWITCH_FALSE),
            targets: vec![f, t],
        }
    }

897
    pub fn successors(&self) -> Successors {
898
        use self::TerminatorKind::*;
N
Niko Matsakis 已提交
899
        match *self {
900 901 902 903 904 905 906 907 908 909 910 911 912
            Resume | Abort | GeneratorDrop | Return | Unreachable |
            Call { destination: None, cleanup: None, .. } => {
                None.into_iter().chain(&[])
            }
            Goto { target: ref t } |
            Call { destination: None, cleanup: Some(ref t), .. } |
            Call { destination: Some((_, ref t)), cleanup: None, .. } |
            Yield { resume: ref t, drop: None, .. } |
            DropAndReplace { target: ref t, unwind: None, .. } |
            Drop { target: ref t, unwind: None, .. } |
            Assert { target: ref t, cleanup: None, .. } |
            FalseUnwind { real_target: ref t, unwind: None } => {
                Some(t).into_iter().chain(&[])
913
            }
914 915 916 917 918 919 920 921 922 923
            Call { destination: Some((_, ref t)), cleanup: Some(ref u), .. } |
            Yield { resume: ref t, drop: Some(ref u), .. } |
            DropAndReplace { target: ref t, unwind: Some(ref u), .. } |
            Drop { target: ref t, unwind: Some(ref u), .. } |
            Assert { target: ref t, cleanup: Some(ref u), .. } |
            FalseUnwind { real_target: ref t, unwind: Some(ref u) } => {
                Some(t).into_iter().chain(slice::from_ref(u))
            }
            SwitchInt { ref targets, .. } => {
                None.into_iter().chain(&targets[..])
924
            }
O
Oliver Schneider 已提交
925
            FalseEdges { ref real_target, ref imaginary_targets } => {
926
                Some(real_target).into_iter().chain(&imaginary_targets[..])
O
Oliver Schneider 已提交
927
            }
N
Niko Matsakis 已提交
928 929
        }
    }
930

931
    pub fn successors_mut(&mut self) -> SuccessorsMut {
932
        use self::TerminatorKind::*;
933
        match *self {
934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953
            Resume | Abort | GeneratorDrop | Return | Unreachable |
            Call { destination: None, cleanup: None, .. } => {
                None.into_iter().chain(&mut [])
            }
            Goto { target: ref mut t } |
            Call { destination: None, cleanup: Some(ref mut t), .. } |
            Call { destination: Some((_, ref mut t)), cleanup: None, .. } |
            Yield { resume: ref mut t, drop: None, .. } |
            DropAndReplace { target: ref mut t, unwind: None, .. } |
            Drop { target: ref mut t, unwind: None, .. } |
            Assert { target: ref mut t, cleanup: None, .. } |
            FalseUnwind { real_target: ref mut t, unwind: None } => {
                Some(t).into_iter().chain(&mut [])
            }
            Call { destination: Some((_, ref mut t)), cleanup: Some(ref mut u), .. } |
            Yield { resume: ref mut t, drop: Some(ref mut u), .. } |
            DropAndReplace { target: ref mut t, unwind: Some(ref mut u), .. } |
            Drop { target: ref mut t, unwind: Some(ref mut u), .. } |
            Assert { target: ref mut t, cleanup: Some(ref mut u), .. } |
            FalseUnwind { real_target: ref mut t, unwind: Some(ref mut u) } => {
S
Stjepan Glavina 已提交
954
                Some(t).into_iter().chain(slice::from_mut(u))
955 956 957
            }
            SwitchInt { ref mut targets, .. } => {
                None.into_iter().chain(&mut targets[..])
958
            }
O
Oliver Schneider 已提交
959
            FalseEdges { ref mut real_target, ref mut imaginary_targets } => {
960
                Some(real_target).into_iter().chain(&mut imaginary_targets[..])
O
Oliver Schneider 已提交
961 962 963 964 965 966 967 968
            }
        }
    }

    pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> {
        match *self {
            TerminatorKind::Goto { .. } |
            TerminatorKind::Resume |
D
David Henningsson 已提交
969
            TerminatorKind::Abort |
O
Oliver Schneider 已提交
970 971 972 973 974 975 976 977 978 979 980
            TerminatorKind::Return |
            TerminatorKind::Unreachable |
            TerminatorKind::GeneratorDrop |
            TerminatorKind::Yield { .. } |
            TerminatorKind::SwitchInt { .. } |
            TerminatorKind::FalseEdges { .. } => {
                None
            },
            TerminatorKind::Call { cleanup: ref mut unwind, .. } |
            TerminatorKind::Assert { cleanup: ref mut unwind, .. } |
            TerminatorKind::DropAndReplace { ref mut unwind, .. } |
981 982
            TerminatorKind::Drop { ref mut unwind, .. } |
            TerminatorKind::FalseUnwind { ref mut unwind, .. } => {
O
Oliver Schneider 已提交
983 984
                Some(unwind)
            }
985 986
        }
    }
N
Niko Matsakis 已提交
987 988
}

989
impl<'tcx> BasicBlockData<'tcx> {
S
Simonas Kazlauskas 已提交
990
    pub fn new(terminator: Option<Terminator<'tcx>>) -> BasicBlockData<'tcx> {
N
Niko Matsakis 已提交
991 992
        BasicBlockData {
            statements: vec![],
993
            terminator,
994
            is_cleanup: false,
N
Niko Matsakis 已提交
995 996
        }
    }
S
Simonas Kazlauskas 已提交
997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008

    /// Accessor for terminator.
    ///
    /// Terminator may not be None after construction of the basic block is complete. This accessor
    /// provides a convenience way to reach the terminator.
    pub fn terminator(&self) -> &Terminator<'tcx> {
        self.terminator.as_ref().expect("invalid terminator state")
    }

    pub fn terminator_mut(&mut self) -> &mut Terminator<'tcx> {
        self.terminator.as_mut().expect("invalid terminator state")
    }
J
John Kåre Alsaker 已提交
1009 1010 1011 1012

    pub fn retain_statements<F>(&mut self, mut f: F) where F: FnMut(&mut Statement) -> bool {
        for s in &mut self.statements {
            if !f(s) {
1013
                s.make_nop();
J
John Kåre Alsaker 已提交
1014 1015 1016
            }
        }
    }
1017

1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052
    pub fn expand_statements<F, I>(&mut self, mut f: F)
        where F: FnMut(&mut Statement<'tcx>) -> Option<I>,
              I: iter::TrustedLen<Item = Statement<'tcx>>
    {
        // Gather all the iterators we'll need to splice in, and their positions.
        let mut splices: Vec<(usize, I)> = vec![];
        let mut extra_stmts = 0;
        for (i, s) in self.statements.iter_mut().enumerate() {
            if let Some(mut new_stmts) = f(s) {
                if let Some(first) = new_stmts.next() {
                    // We can already store the first new statement.
                    *s = first;

                    // Save the other statements for optimized splicing.
                    let remaining = new_stmts.size_hint().0;
                    if remaining > 0 {
                        splices.push((i + 1 + extra_stmts, new_stmts));
                        extra_stmts += remaining;
                    }
                } else {
                    s.make_nop();
                }
            }
        }

        // Splice in the new statements, from the end of the block.
        // FIXME(eddyb) This could be more efficient with a "gap buffer"
        // where a range of elements ("gap") is left uninitialized, with
        // splicing adding new elements to the end of that gap and moving
        // existing elements from before the gap to the end of the gap.
        // For now, this is safe code, emulating a gap but initializing it.
        let mut gap = self.statements.len()..self.statements.len()+extra_stmts;
        self.statements.resize(gap.end, Statement {
            source_info: SourceInfo {
                span: DUMMY_SP,
1053
                scope: OUTERMOST_SOURCE_SCOPE
1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068
            },
            kind: StatementKind::Nop
        });
        for (splice_start, new_stmts) in splices.into_iter().rev() {
            let splice_end = splice_start + new_stmts.size_hint().0;
            while gap.end > splice_end {
                gap.start -= 1;
                gap.end -= 1;
                self.statements.swap(gap.start, gap.end);
            }
            self.statements.splice(splice_start..splice_end, new_stmts);
            gap.end = splice_start;
        }
    }

1069 1070 1071 1072 1073 1074 1075
    pub fn visitable(&self, index: usize) -> &dyn MirVisitable<'tcx> {
        if index < self.statements.len() {
            &self.statements[index]
        } else {
            &self.terminator
        }
    }
N
Niko Matsakis 已提交
1076 1077
}

1078
impl<'tcx> Debug for TerminatorKind<'tcx> {
1079
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
J
Jorge Aparicio 已提交
1080
        self.fmt_head(fmt)?;
1081
        let successor_count = self.successors().count();
1082
        let labels = self.fmt_successor_labels();
1083
        assert_eq!(successor_count, labels.len());
1084

1085
        match successor_count {
1086 1087
            0 => Ok(()),

1088
            1 => write!(fmt, " -> {:?}", self.successors().nth(0).unwrap()),
1089 1090

            _ => {
J
Jorge Aparicio 已提交
1091
                write!(fmt, " -> [")?;
1092
                for (i, target) in self.successors().enumerate() {
1093
                    if i > 0 {
J
Jorge Aparicio 已提交
1094
                        write!(fmt, ", ")?;
1095
                    }
J
Jorge Aparicio 已提交
1096
                    write!(fmt, "{}: {:?}", labels[i], target)?;
1097 1098 1099 1100 1101 1102 1103 1104
                }
                write!(fmt, "]")
            }

        }
    }
}

1105
impl<'tcx> TerminatorKind<'tcx> {
1106
    /// Write the "head" part of the terminator; that is, its name and the data it uses to pick the
B
Bastien Orivel 已提交
1107
    /// successor basic block, if any. The only information not included is the list of possible
1108
    /// successors, which may be rendered differently between the text and the graphviz format.
1109
    pub fn fmt_head<W: Write>(&self, fmt: &mut W) -> fmt::Result {
1110
        use self::TerminatorKind::*;
N
Niko Matsakis 已提交
1111
        match *self {
1112
            Goto { .. } => write!(fmt, "goto"),
O
Oliver Schneider 已提交
1113
            SwitchInt { discr: ref place, .. } => write!(fmt, "switchInt({:?})", place),
1114
            Return => write!(fmt, "return"),
J
John Kåre Alsaker 已提交
1115
            GeneratorDrop => write!(fmt, "generator_drop"),
1116
            Resume => write!(fmt, "resume"),
D
David Henningsson 已提交
1117
            Abort => write!(fmt, "abort"),
J
John Kåre Alsaker 已提交
1118
            Yield { ref value, .. } => write!(fmt, "_1 = suspend({:?})", value),
1119
            Unreachable => write!(fmt, "unreachable"),
1120 1121 1122
            Drop { ref location, .. } => write!(fmt, "drop({:?})", location),
            DropAndReplace { ref location, ref value, .. } =>
                write!(fmt, "replace({:?} <- {:?})", location, value),
S
Simonas Kazlauskas 已提交
1123 1124
            Call { ref func, ref args, ref destination, .. } => {
                if let Some((ref destination, _)) = *destination {
J
Jorge Aparicio 已提交
1125
                    write!(fmt, "{:?} = ", destination)?;
1126
                }
J
Jorge Aparicio 已提交
1127
                write!(fmt, "{:?}(", func)?;
1128 1129
                for (index, arg) in args.iter().enumerate() {
                    if index > 0 {
J
Jorge Aparicio 已提交
1130
                        write!(fmt, ", ")?;
1131
                    }
J
Jorge Aparicio 已提交
1132
                    write!(fmt, "{:?}", arg)?;
1133 1134
                }
                write!(fmt, ")")
1135
            }
1136 1137 1138 1139 1140
            Assert { ref cond, expected, ref msg, .. } => {
                write!(fmt, "assert(")?;
                if !expected {
                    write!(fmt, "!")?;
                }
1141
                write!(fmt, "{:?}, \"{:?}\")", cond, msg)
O
Oliver Schneider 已提交
1142
            },
1143 1144
            FalseEdges { .. } => write!(fmt, "falseEdges"),
            FalseUnwind { .. } => write!(fmt, "falseUnwind"),
1145 1146 1147
        }
    }

1148
    /// Return the list of labels for the edges to the successor basic blocks.
1149
    pub fn fmt_successor_labels(&self) -> Vec<Cow<'static, str>> {
1150
        use self::TerminatorKind::*;
1151
        match *self {
D
David Henningsson 已提交
1152
            Return | Resume | Abort | Unreachable | GeneratorDrop => vec![],
1153
            Goto { .. } => vec!["".into()],
O
Oliver Schneider 已提交
1154
            SwitchInt { ref values, switch_ty, .. } => {
1155 1156
                let size = ty::tls::with(|tcx| {
                    let param_env = ty::ParamEnv::empty();
1157
                    let switch_ty = tcx.lift_to_global(&switch_ty).unwrap();
O
Oliver Schneider 已提交
1158
                    tcx.layout_of(param_env.and(switch_ty)).unwrap().size
1159
                });
1160
                values.iter()
O
Oliver Schneider 已提交
1161 1162 1163
                      .map(|&u| {
                          let mut s = String::new();
                          print_miri_value(
O
Oliver Schneider 已提交
1164
                              Value::Scalar(Scalar::Bits { bits: u, defined: size.bits() as u8 }),
O
Oliver Schneider 已提交
1165 1166 1167 1168
                              switch_ty,
                              &mut s,
                          ).unwrap();
                          s.into()
1169
                      })
1170
                      .chain(iter::once(String::from("otherwise").into()))
1171
                      .collect()
N
Niko Matsakis 已提交
1172
            }
S
Simonas Kazlauskas 已提交
1173 1174 1175 1176 1177
            Call { destination: Some(_), cleanup: Some(_), .. } =>
                vec!["return".into_cow(), "unwind".into_cow()],
            Call { destination: Some(_), cleanup: None, .. } => vec!["return".into_cow()],
            Call { destination: None, cleanup: Some(_), .. } => vec!["unwind".into_cow()],
            Call { destination: None, cleanup: None, .. } => vec![],
J
John Kåre Alsaker 已提交
1178
            Yield { drop: Some(_), .. } =>
J
John Kåre Alsaker 已提交
1179
                vec!["resume".into_cow(), "drop".into_cow()],
J
John Kåre Alsaker 已提交
1180
            Yield { drop: None, .. } => vec!["resume".into_cow()],
1181
            DropAndReplace { unwind: None, .. } |
1182
            Drop { unwind: None, .. } => vec!["return".into_cow()],
1183 1184 1185 1186
            DropAndReplace { unwind: Some(_), .. } |
            Drop { unwind: Some(_), .. } => {
                vec!["return".into_cow(), "unwind".into_cow()]
            }
1187 1188
            Assert { cleanup: None, .. } => vec!["".into()],
            Assert { .. } =>
O
Oliver Schneider 已提交
1189 1190 1191 1192 1193 1194
                vec!["success".into_cow(), "unwind".into_cow()],
            FalseEdges { ref imaginary_targets, .. } => {
                let mut l = vec!["real".into()];
                l.resize(imaginary_targets.len() + 1, "imaginary".into());
                l
            }
1195 1196
            FalseUnwind { unwind: Some(_), .. } => vec!["real".into(), "cleanup".into()],
            FalseUnwind { unwind: None, .. } => vec!["real".into()],
N
Niko Matsakis 已提交
1197 1198 1199 1200 1201 1202 1203
        }
    }
}

///////////////////////////////////////////////////////////////////////////
// Statements

1204
#[derive(Clone, RustcEncodable, RustcDecodable)]
1205
pub struct Statement<'tcx> {
1206
    pub source_info: SourceInfo,
1207
    pub kind: StatementKind<'tcx>,
N
Niko Matsakis 已提交
1208 1209
}

1210 1211 1212 1213 1214 1215
impl<'tcx> Statement<'tcx> {
    /// Changes a statement to a nop. This is both faster than deleting instructions and avoids
    /// invalidating statement indices in `Location`s.
    pub fn make_nop(&mut self) {
        self.kind = StatementKind::Nop
    }
1216 1217 1218 1219 1220 1221 1222 1223

    /// Changes a statement to a nop and returns the original statement.
    pub fn replace_nop(&mut self) -> Self {
        Statement {
            source_info: self.source_info,
            kind: mem::replace(&mut self.kind, StatementKind::Nop)
        }
    }
1224 1225
}

1226
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
1227
pub enum StatementKind<'tcx> {
O
Oliver Schneider 已提交
1228 1229
    /// Write the RHS Rvalue to the LHS Place.
    Assign(Place<'tcx>, Rvalue<'tcx>),
1230

1231 1232 1233 1234
    /// This represents all the reading that a pattern match may do
    /// (e.g. inspecting constants and discriminant values).
    ReadForMatch(Place<'tcx>),

O
Oliver Schneider 已提交
1235 1236
    /// Write the discriminant for a variant to the enum Place.
    SetDiscriminant { place: Place<'tcx>, variant_index: usize },
1237 1238

    /// Start a live range for the storage of the local.
1239
    StorageLive(Local),
1240 1241

    /// End the current live range for the storage of the local.
1242
    StorageDead(Local),
1243

1244
    /// Execute a piece of inline Assembly.
1245
    InlineAsm {
A
Ariel Ben-Yehuda 已提交
1246
        asm: Box<InlineAsm>,
O
Oliver Schneider 已提交
1247
        outputs: Vec<Place<'tcx>>,
1248 1249 1250
        inputs: Vec<Operand<'tcx>>
    },

O
Oliver Schneider 已提交
1251
    /// Assert the given places to be valid inhabitants of their type.  These statements are
R
Ralf Jung 已提交
1252 1253
    /// currently only interpreted by miri and only generated when "-Z mir-emit-validate" is passed.
    /// See <https://internals.rust-lang.org/t/types-as-contracts/5562/73> for more details.
O
Oliver Schneider 已提交
1254
    Validate(ValidationOp, Vec<ValidationOperand<'tcx, Place<'tcx>>>),
1255

1256
    /// Mark one terminating point of a region scope (i.e. static region).
1257
    /// (The starting point(s) arise implicitly from borrows.)
1258
    EndRegion(region::Scope),
1259

D
David Wood 已提交
1260 1261 1262 1263 1264 1265 1266
    /// Encodes a user's type assertion. These need to be preserved intact so that NLL can respect
    /// them. For example:
    ///
    ///     let (a, b): (T, U) = y;
    ///
    /// Here we would insert a `UserAssertTy<(T, U)>(y)` instruction to check that the type of `y`
    /// is the right thing.
1267 1268 1269 1270 1271 1272 1273 1274
    ///
    /// `CanonicalTy` is used to capture "inference variables" from the user's types. For example:
    ///
    ///     let x: Vec<_> = ...;
    ///     let y: &u32 = ...;
    ///
    /// would result in `Vec<?0>` and `&'?0 u32` respectively (where `?0` is a canonicalized
    /// variable).
1275
    UserAssertTy(CanonicalTy<'tcx>, Local),
D
David Wood 已提交
1276

1277 1278
    /// No-op. Useful for deleting instructions without affecting statement indices.
    Nop,
N
Niko Matsakis 已提交
1279 1280
}

R
Ralf Jung 已提交
1281 1282
/// The `ValidationOp` describes what happens with each of the operands of a
/// `Validate` statement.
1283
#[derive(Copy, Clone, RustcEncodable, RustcDecodable, PartialEq, Eq)]
1284
pub enum ValidationOp {
O
Oliver Schneider 已提交
1285
    /// Recursively traverse the place following the type and validate that all type
R
Ralf Jung 已提交
1286
    /// invariants are maintained.  Furthermore, acquire exclusive/read-only access to the
O
Oliver Schneider 已提交
1287
    /// memory reachable from the place.
1288
    Acquire,
R
Ralf Jung 已提交
1289 1290
    /// Recursive traverse the *mutable* part of the type and relinquish all exclusive
    /// access.
1291
    Release,
R
Ralf Jung 已提交
1292 1293
    /// Recursive traverse the *mutable* part of the type and relinquish all exclusive
    /// access *until* the given region ends.  Then, access will be recovered.
1294
    Suspend(region::Scope),
1295 1296
}

1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308
impl Debug for ValidationOp {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        use self::ValidationOp::*;
        match *self {
            Acquire => write!(fmt, "Acquire"),
            Release => write!(fmt, "Release"),
            // (reuse lifetime rendering policy from ppaux.)
            Suspend(ref ce) => write!(fmt, "Suspend({})", ty::ReScope(*ce)),
        }
    }
}

1309
// This is generic so that it can be reused by miri
1310
#[derive(Clone, RustcEncodable, RustcDecodable)]
1311
pub struct ValidationOperand<'tcx, T> {
O
Oliver Schneider 已提交
1312
    pub place: T,
1313
    pub ty: Ty<'tcx>,
1314
    pub re: Option<region::Scope>,
1315 1316 1317
    pub mutbl: hir::Mutability,
}

1318
impl<'tcx, T: Debug> Debug for ValidationOperand<'tcx, T> {
1319
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
O
Oliver Schneider 已提交
1320
        write!(fmt, "{:?}: {:?}", self.place, self.ty)?;
1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331
        if let Some(ce) = self.re {
            // (reuse lifetime rendering policy from ppaux.)
            write!(fmt, "/{}", ty::ReScope(ce))?;
        }
        if let hir::MutImmutable = self.mutbl {
            write!(fmt, " (imm)")?;
        }
        Ok(())
    }
}

1332
impl<'tcx> Debug for Statement<'tcx> {
1333
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
N
Niko Matsakis 已提交
1334 1335
        use self::StatementKind::*;
        match self.kind {
O
Oliver Schneider 已提交
1336
            Assign(ref place, ref rv) => write!(fmt, "{:?} = {:?}", place, rv),
1337
            ReadForMatch(ref place) => write!(fmt, "ReadForMatch({:?})", place),
1338 1339
            // (reuse lifetime rendering policy from ppaux.)
            EndRegion(ref ce) => write!(fmt, "EndRegion({})", ty::ReScope(*ce)),
O
Oliver Schneider 已提交
1340 1341 1342 1343 1344
            Validate(ref op, ref places) => write!(fmt, "Validate({:?}, {:?})", op, places),
            StorageLive(ref place) => write!(fmt, "StorageLive({:?})", place),
            StorageDead(ref place) => write!(fmt, "StorageDead({:?})", place),
            SetDiscriminant { ref place, variant_index } => {
                write!(fmt, "discriminant({:?}) = {:?}", place, variant_index)
1345 1346 1347 1348
            },
            InlineAsm { ref asm, ref outputs, ref inputs } => {
                write!(fmt, "asm!({:?} : {:?} : {:?})", asm, outputs, inputs)
            },
1349 1350
            UserAssertTy(ref c_ty, ref local) => write!(fmt, "UserAssertTy({:?}, {:?})",
                                                        c_ty, local),
1351
            Nop => write!(fmt, "nop"),
N
Niko Matsakis 已提交
1352 1353 1354
        }
    }
}
1355

N
Niko Matsakis 已提交
1356
///////////////////////////////////////////////////////////////////////////
O
Oliver Schneider 已提交
1357
// Places
N
Niko Matsakis 已提交
1358 1359 1360

/// A path to a value; something that can be evaluated without
/// changing or disturbing program state.
1361
#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
O
Oliver Schneider 已提交
1362
pub enum Place<'tcx> {
1363 1364
    /// local variable
    Local(Local),
N
Niko Matsakis 已提交
1365 1366

    /// static or static mut variable
1367
    Static(Box<Static<'tcx>>),
N
Niko Matsakis 已提交
1368

O
Oliver Schneider 已提交
1369 1370
    /// projection out of a place (access a field, deref a pointer, etc)
    Projection(Box<PlaceProjection<'tcx>>),
N
Niko Matsakis 已提交
1371 1372
}

1373 1374
/// The def-id of a static, along with its normalized type (which is
/// stored to avoid requiring normalization when reading MIR).
1375
#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
1376 1377 1378 1379 1380
pub struct Static<'tcx> {
    pub def_id: DefId,
    pub ty: Ty<'tcx>,
}

1381 1382 1383 1384 1385
impl_stable_hash_for!(struct Static<'tcx> {
    def_id,
    ty
});

N
Niko Matsakis 已提交
1386 1387
/// The `Projection` data structure defines things of the form `B.x`
/// or `*B` or `B[index]`. Note that it is parameterized because it is
O
Oliver Schneider 已提交
1388 1389
/// shared between `Constant` and `Place`. See the aliases
/// `PlaceProjection` etc below.
1390
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
1391
pub struct Projection<'tcx, B, V, T> {
N
Niko Matsakis 已提交
1392
    pub base: B,
1393
    pub elem: ProjectionElem<'tcx, V, T>,
N
Niko Matsakis 已提交
1394 1395
}

1396
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
1397
pub enum ProjectionElem<'tcx, V, T> {
N
Niko Matsakis 已提交
1398
    Deref,
1399
    Field(Field, T),
N
Niko Matsakis 已提交
1400 1401
    Index(V),

1402 1403 1404 1405 1406 1407 1408 1409 1410
    /// These indices are generated by slice patterns. Easiest to explain
    /// by example:
    ///
    /// ```
    /// [X, _, .._, _, _] => { offset: 0, min_length: 4, from_end: false },
    /// [_, X, .._, _, _] => { offset: 1, min_length: 4, from_end: false },
    /// [_, _, .._, X, _] => { offset: 2, min_length: 4, from_end: true },
    /// [_, _, .._, _, X] => { offset: 1, min_length: 4, from_end: true },
    /// ```
N
Niko Matsakis 已提交
1411
    ConstantIndex {
1412 1413 1414 1415 1416 1417
        /// index or -index (in Python terms), depending on from_end
        offset: u32,
        /// thing being indexed must be at least this long
        min_length: u32,
        /// counting backwards from end?
        from_end: bool,
N
Niko Matsakis 已提交
1418 1419
    },

1420 1421 1422 1423 1424 1425 1426 1427
    /// These indices are generated by slice patterns.
    ///
    /// slice[from:-to] in Python terms.
    Subslice {
        from: u32,
        to: u32,
    },

1428 1429 1430
    /// "Downcast" to a variant of an ADT. Currently, we only introduce
    /// this for ADTs with more than one variant. It may be better to
    /// just introduce it always, or always for enums.
1431
    Downcast(&'tcx AdtDef, usize),
N
Niko Matsakis 已提交
1432 1433
}

O
Oliver Schneider 已提交
1434
/// Alias for projections as they appear in places, where the base is a place
1435
/// and the index is a local.
O
Oliver Schneider 已提交
1436
pub type PlaceProjection<'tcx> = Projection<'tcx, Place<'tcx>, Local, Ty<'tcx>>;
N
Niko Matsakis 已提交
1437

O
Oliver Schneider 已提交
1438
/// Alias for projections as they appear in places, where the base is a place
1439
/// and the index is a local.
O
Oliver Schneider 已提交
1440
pub type PlaceElem<'tcx> = ProjectionElem<'tcx, Local, Ty<'tcx>>;
N
Niko Matsakis 已提交
1441

O
Oliver Schneider 已提交
1442
newtype_index!(Field { DEBUG_FORMAT = "field[{}]" });
N
Niko Matsakis 已提交
1443

O
Oliver Schneider 已提交
1444 1445
impl<'tcx> Place<'tcx> {
    pub fn field(self, f: Field, ty: Ty<'tcx>) -> Place<'tcx> {
1446
        self.elem(ProjectionElem::Field(f, ty))
N
Niko Matsakis 已提交
1447 1448
    }

O
Oliver Schneider 已提交
1449
    pub fn deref(self) -> Place<'tcx> {
N
Niko Matsakis 已提交
1450 1451 1452
        self.elem(ProjectionElem::Deref)
    }

O
Oliver Schneider 已提交
1453
    pub fn downcast(self, adt_def: &'tcx AdtDef, variant_index: usize) -> Place<'tcx> {
1454 1455 1456
        self.elem(ProjectionElem::Downcast(adt_def, variant_index))
    }

O
Oliver Schneider 已提交
1457
    pub fn index(self, index: Local) -> Place<'tcx> {
N
Niko Matsakis 已提交
1458 1459 1460
        self.elem(ProjectionElem::Index(index))
    }

O
Oliver Schneider 已提交
1461 1462
    pub fn elem(self, elem: PlaceElem<'tcx>) -> Place<'tcx> {
        Place::Projection(Box::new(PlaceProjection {
1463
            base: self,
1464
            elem,
1465
        }))
N
Niko Matsakis 已提交
1466 1467 1468
    }
}

O
Oliver Schneider 已提交
1469
impl<'tcx> Debug for Place<'tcx> {
1470
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
O
Oliver Schneider 已提交
1471
        use self::Place::*;
N
Niko Matsakis 已提交
1472 1473

        match *self {
1474
            Local(id) => write!(fmt, "{:?}", id),
1475 1476
            Static(box self::Static { def_id, ty }) =>
                write!(fmt, "({}: {:?})", ty::tls::with(|tcx| tcx.item_path_str(def_id)), ty),
N
Niko Matsakis 已提交
1477 1478
            Projection(ref data) =>
                match data.elem {
1479
                    ProjectionElem::Downcast(ref adt_def, index) =>
1480
                        write!(fmt, "({:?} as {})", data.base, adt_def.variants[index].name),
N
Niko Matsakis 已提交
1481
                    ProjectionElem::Deref =>
1482
                        write!(fmt, "(*{:?})", data.base),
1483 1484
                    ProjectionElem::Field(field, ty) =>
                        write!(fmt, "({:?}.{:?}: {:?})", data.base, field.index(), ty),
N
Niko Matsakis 已提交
1485
                    ProjectionElem::Index(ref index) =>
1486
                        write!(fmt, "{:?}[{:?}]", data.base, index),
N
Niko Matsakis 已提交
1487
                    ProjectionElem::ConstantIndex { offset, min_length, from_end: false } =>
1488
                        write!(fmt, "{:?}[{:?} of {:?}]", data.base, offset, min_length),
N
Niko Matsakis 已提交
1489
                    ProjectionElem::ConstantIndex { offset, min_length, from_end: true } =>
1490
                        write!(fmt, "{:?}[-{:?} of {:?}]", data.base, offset, min_length),
1491
                    ProjectionElem::Subslice { from, to } if to == 0 =>
1492
                        write!(fmt, "{:?}[{:?}:]", data.base, from),
1493 1494 1495 1496 1497 1498
                    ProjectionElem::Subslice { from, to } if from == 0 =>
                        write!(fmt, "{:?}[:-{:?}]", data.base, to),
                    ProjectionElem::Subslice { from, to } =>
                        write!(fmt, "{:?}[{:?}:-{:?}]", data.base,
                               from, to),

N
Niko Matsakis 已提交
1499 1500 1501 1502 1503
                },
        }
    }
}

N
Niko Matsakis 已提交
1504 1505 1506
///////////////////////////////////////////////////////////////////////////
// Scopes

1507
newtype_index!(SourceScope
O
Oliver Schneider 已提交
1508 1509
    {
        DEBUG_FORMAT = "scope[{}]",
1510
        const OUTERMOST_SOURCE_SCOPE = 0,
O
Oliver Schneider 已提交
1511
    });
N
Niko Matsakis 已提交
1512 1513

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
1514
pub struct SourceScopeData {
1515
    pub span: Span,
1516
    pub parent_scope: Option<SourceScope>,
N
Niko Matsakis 已提交
1517 1518
}

1519 1520 1521 1522 1523 1524 1525 1526
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct SourceScopeLocalData {
    /// A NodeId with lint levels equivalent to this scope's lint levels.
    pub lint_root: ast::NodeId,
    /// The unsafe block that contains this node.
    pub safety: Safety,
}

N
Niko Matsakis 已提交
1527 1528
///////////////////////////////////////////////////////////////////////////
// Operands
N
Niko Matsakis 已提交
1529

1530
/// These are values that can appear inside an rvalue (or an index
O
Oliver Schneider 已提交
1531
/// place). They are intentionally limited to prevent rvalues from
1532
/// being nested in one another.
1533
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)]
1534
pub enum Operand<'tcx> {
O
Oliver Schneider 已提交
1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545
    /// Copy: The value must be available for use afterwards.
    ///
    /// This implies that the type of the place must be `Copy`; this is true
    /// by construction during build, but also checked by the MIR type checker.
    Copy(Place<'tcx>),
    /// Move: The value (including old borrows of it) will not be used again.
    ///
    /// Safe for values of all types (modulo future developments towards `?Move`).
    /// Correct usage patterns are enforced by the borrow checker for safe code.
    /// `Copy` may be converted to `Move` to enable "last-use" optimizations.
    Move(Place<'tcx>),
A
Ariel Ben-Yehuda 已提交
1546
    Constant(Box<Constant<'tcx>>),
N
Niko Matsakis 已提交
1547 1548
}

1549
impl<'tcx> Debug for Operand<'tcx> {
1550
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
N
Niko Matsakis 已提交
1551 1552 1553
        use self::Operand::*;
        match *self {
            Constant(ref a) => write!(fmt, "{:?}", a),
O
Oliver Schneider 已提交
1554 1555
            Copy(ref place) => write!(fmt, "{:?}", place),
            Move(ref place) => write!(fmt, "move {:?}", place),
N
Niko Matsakis 已提交
1556 1557 1558 1559
        }
    }
}

A
Ariel Ben-Yehuda 已提交
1560
impl<'tcx> Operand<'tcx> {
1561
    pub fn function_handle<'a>(
D
Douglas Campos 已提交
1562
        tcx: TyCtxt<'a, 'tcx, 'tcx>,
1563 1564 1565 1566
        def_id: DefId,
        substs: &'tcx Substs<'tcx>,
        span: Span,
    ) -> Self {
1567
        let ty = tcx.type_of(def_id).subst(tcx, substs);
A
Ariel Ben-Yehuda 已提交
1568
        Operand::Constant(box Constant {
1569
            span,
1570
            ty,
1571
            literal: Literal::Value {
1572
                value: ty::Const::zero_sized(tcx, ty),
1573
            },
A
Ariel Ben-Yehuda 已提交
1574 1575 1576
        })
    }

1577 1578 1579 1580 1581 1582
    pub fn to_copy(&self) -> Self {
        match *self {
            Operand::Copy(_) | Operand::Constant(_) => self.clone(),
            Operand::Move(ref place) => Operand::Copy(place.clone())
        }
    }
A
Ariel Ben-Yehuda 已提交
1583 1584
}

N
Niko Matsakis 已提交
1585
///////////////////////////////////////////////////////////////////////////
1586
/// Rvalues
N
Niko Matsakis 已提交
1587

1588
#[derive(Clone, RustcEncodable, RustcDecodable)]
1589
pub enum Rvalue<'tcx> {
1590
    /// x (either a move or copy, depending on type of x)
1591
    Use(Operand<'tcx>),
N
Niko Matsakis 已提交
1592

1593
    /// [x; 32]
O
Oliver Schneider 已提交
1594
    Repeat(Operand<'tcx>, u64),
N
Niko Matsakis 已提交
1595

1596
    /// &x or &mut x
O
Oliver Schneider 已提交
1597
    Ref(Region<'tcx>, BorrowKind, Place<'tcx>),
N
Niko Matsakis 已提交
1598

1599
    /// length of a [X] or [X;n] value
O
Oliver Schneider 已提交
1600
    Len(Place<'tcx>),
N
Niko Matsakis 已提交
1601

1602
    Cast(CastKind, Operand<'tcx>, Ty<'tcx>),
N
Niko Matsakis 已提交
1603

1604
    BinaryOp(BinOp, Operand<'tcx>, Operand<'tcx>),
J
James Miller 已提交
1605
    CheckedBinaryOp(BinOp, Operand<'tcx>, Operand<'tcx>),
N
Niko Matsakis 已提交
1606

1607
    NullaryOp(NullOp, Ty<'tcx>),
1608
    UnaryOp(UnOp, Operand<'tcx>),
N
Niko Matsakis 已提交
1609

1610 1611 1612 1613
    /// Read the discriminant of an ADT.
    ///
    /// Undefined (i.e. no effort is made to make it defined, but there’s no reason why it cannot
    /// be defined to return, say, a 0) if ADT is not an enum.
O
Oliver Schneider 已提交
1614
    Discriminant(Place<'tcx>),
1615

1616 1617 1618 1619 1620
    /// Create an aggregate value, like a tuple or struct.  This is
    /// only needed because we want to distinguish `dest = Foo { x:
    /// ..., y: ... }` from `dest.x = ...; dest.y = ...;` in the case
    /// that `Foo` has a destructor. These rvalues can be optimized
    /// away after type-checking and before lowering.
A
Ariel Ben-Yehuda 已提交
1621
    Aggregate(Box<AggregateKind<'tcx>>, Vec<Operand<'tcx>>),
N
Niko Matsakis 已提交
1622 1623
}

1624
#[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
N
Niko Matsakis 已提交
1625 1626 1627 1628 1629 1630
pub enum CastKind {
    Misc,

    /// Convert unique, zero-sized type for a fn to fn()
    ReifyFnPointer,

1631 1632 1633
    /// Convert non capturing closure to fn()
    ClosureFnPointer,

N
Niko Matsakis 已提交
1634 1635 1636 1637
    /// Convert safe fn() to unsafe fn()
    UnsafeFnPointer,

    /// "Unsize" -- convert a thin-or-fat pointer to a fat pointer.
I
Irina Popa 已提交
1638
    /// codegen must figure out the details once full monomorphization
N
Niko Matsakis 已提交
1639 1640 1641 1642 1643 1644
    /// is known. For example, this could be used to cast from a
    /// `&[i32;N]` to a `&[i32]`, or a `Box<T>` to a `Box<Trait>`
    /// (presuming `T: Trait`).
    Unsize,
}

1645
#[derive(Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
1646
pub enum AggregateKind<'tcx> {
S
Simonas Kazlauskas 已提交
1647 1648
    /// The type is of the element
    Array(Ty<'tcx>),
N
Niko Matsakis 已提交
1649
    Tuple,
O
Oliver Schneider 已提交
1650

1651 1652
    /// The second field is the variant index. It's equal to 0 for struct
    /// and union expressions. The fourth field is
O
Oliver Schneider 已提交
1653 1654 1655
    /// active field number and is present only for union expressions
    /// -- e.g. for a union expression `SomeUnion { c: .. }`, the
    /// active field index would identity the field `c`
1656
    Adt(&'tcx AdtDef, usize, &'tcx Substs<'tcx>, Option<usize>),
O
Oliver Schneider 已提交
1657

1658
    Closure(DefId, ClosureSubsts<'tcx>),
1659
    Generator(DefId, GeneratorSubsts<'tcx>, hir::GeneratorMovability),
N
Niko Matsakis 已提交
1660 1661
}

1662
#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
N
Niko Matsakis 已提交
1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695
pub enum BinOp {
    /// The `+` operator (addition)
    Add,
    /// The `-` operator (subtraction)
    Sub,
    /// The `*` operator (multiplication)
    Mul,
    /// The `/` operator (division)
    Div,
    /// The `%` operator (modulus)
    Rem,
    /// The `^` operator (bitwise xor)
    BitXor,
    /// The `&` operator (bitwise and)
    BitAnd,
    /// The `|` operator (bitwise or)
    BitOr,
    /// The `<<` operator (shift left)
    Shl,
    /// The `>>` operator (shift right)
    Shr,
    /// The `==` operator (equality)
    Eq,
    /// The `<` operator (less than)
    Lt,
    /// The `<=` operator (less than or equal to)
    Le,
    /// The `!=` operator (not equal to)
    Ne,
    /// The `>=` operator (greater than or equal to)
    Ge,
    /// The `>` operator (greater than)
    Gt,
1696 1697
    /// The `ptr.offset` operator
    Offset,
N
Niko Matsakis 已提交
1698 1699
}

J
James Miller 已提交
1700 1701 1702 1703 1704 1705 1706 1707 1708 1709
impl BinOp {
    pub fn is_checkable(self) -> bool {
        use self::BinOp::*;
        match self {
            Add | Sub | Mul | Shl | Shr => true,
            _ => false
        }
    }
}

1710 1711 1712 1713 1714 1715 1716 1717
#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
pub enum NullOp {
    /// Return the size of a value of that type
    SizeOf,
    /// Create a new uninitialized box for a value of that type
    Box,
}

1718
#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
N
Niko Matsakis 已提交
1719 1720 1721 1722
pub enum UnOp {
    /// The `!` operator for logical inversion
    Not,
    /// The `-` operator for negation
1723
    Neg,
N
Niko Matsakis 已提交
1724 1725
}

1726
impl<'tcx> Debug for Rvalue<'tcx> {
1727
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
N
Niko Matsakis 已提交
1728 1729 1730
        use self::Rvalue::*;

        match *self {
O
Oliver Schneider 已提交
1731
            Use(ref place) => write!(fmt, "{:?}", place),
N
Niko Matsakis 已提交
1732
            Repeat(ref a, ref b) => write!(fmt, "[{:?}; {:?}]", a, b),
1733
            Len(ref a) => write!(fmt, "Len({:?})", a),
O
Oliver Schneider 已提交
1734 1735 1736
            Cast(ref kind, ref place, ref ty) => {
                write!(fmt, "{:?} as {:?} ({:?})", place, ty, kind)
            }
1737
            BinaryOp(ref op, ref a, ref b) => write!(fmt, "{:?}({:?}, {:?})", op, a, b),
J
James Miller 已提交
1738 1739 1740
            CheckedBinaryOp(ref op, ref a, ref b) => {
                write!(fmt, "Checked{:?}({:?}, {:?})", op, a, b)
            }
N
Niko Matsakis 已提交
1741
            UnaryOp(ref op, ref a) => write!(fmt, "{:?}({:?})", op, a),
O
Oliver Schneider 已提交
1742
            Discriminant(ref place) => write!(fmt, "discriminant({:?})", place),
1743
            NullaryOp(ref op, ref t) => write!(fmt, "{:?}({:?})", op, t),
O
Oliver Schneider 已提交
1744
            Ref(region, borrow_kind, ref place) => {
1745 1746
                let kind_str = match borrow_kind {
                    BorrowKind::Shared => "",
1747
                    BorrowKind::Mut { .. } | BorrowKind::Unique => "mut ",
1748
                };
1749

R
Ralf Jung 已提交
1750
                // When printing regions, add trailing space if necessary.
R
Ralf Jung 已提交
1751
                let region = if ppaux::verbose() || ppaux::identify_regions() {
1752 1753 1754
                    let mut region = format!("{}", region);
                    if region.len() > 0 { region.push(' '); }
                    region
R
Ralf Jung 已提交
1755 1756 1757
                } else {
                    // Do not even print 'static
                    "".to_owned()
1758
                };
O
Oliver Schneider 已提交
1759
                write!(fmt, "&{}{}{:?}", region, kind_str, place)
1760 1761
            }

O
Oliver Schneider 已提交
1762 1763
            Aggregate(ref kind, ref places) => {
                fn fmt_tuple(fmt: &mut Formatter, places: &[Operand]) -> fmt::Result {
1764
                    let mut tuple_fmt = fmt.debug_tuple("");
O
Oliver Schneider 已提交
1765 1766
                    for place in places {
                        tuple_fmt.field(place);
1767 1768 1769 1770
                    }
                    tuple_fmt.finish()
                }

A
Ariel Ben-Yehuda 已提交
1771
                match **kind {
O
Oliver Schneider 已提交
1772
                    AggregateKind::Array(_) => write!(fmt, "{:?}", places),
1773

1774
                    AggregateKind::Tuple => {
O
Oliver Schneider 已提交
1775
                        match places.len() {
1776
                            0 => write!(fmt, "()"),
O
Oliver Schneider 已提交
1777 1778
                            1 => write!(fmt, "({:?},)", places[0]),
                            _ => fmt_tuple(fmt, places),
1779 1780 1781
                        }
                    }

1782
                    AggregateKind::Adt(adt_def, variant, substs, _) => {
1783
                        let variant_def = &adt_def.variants[variant];
1784

1785
                        ppaux::parameterized(fmt, substs, variant_def.did, &[])?;
1786

1787 1788
                        match variant_def.ctor_kind {
                            CtorKind::Const => Ok(()),
O
Oliver Schneider 已提交
1789
                            CtorKind::Fn => fmt_tuple(fmt, places),
1790
                            CtorKind::Fictive => {
1791
                                let mut struct_fmt = fmt.debug_struct("");
O
Oliver Schneider 已提交
1792
                                for (field, place) in variant_def.fields.iter().zip(places) {
V
Vadim Petrochenkov 已提交
1793
                                    struct_fmt.field(&field.ident.as_str(), place);
1794 1795 1796 1797 1798 1799
                                }
                                struct_fmt.finish()
                            }
                        }
                    }

1800
                    AggregateKind::Closure(def_id, _) => ty::tls::with(|tcx| {
1801
                        if let Some(node_id) = tcx.hir.as_local_node_id(def_id) {
F
Felix S. Klock II 已提交
1802 1803 1804 1805 1806
                            let name = if tcx.sess.opts.debugging_opts.span_free_formats {
                                format!("[closure@{:?}]", node_id)
                            } else {
                                format!("[closure@{:?}]", tcx.hir.span(node_id))
                            };
1807 1808 1809
                            let mut struct_fmt = fmt.debug_struct(&name);

                            tcx.with_freevars(node_id, |freevars| {
O
Oliver Schneider 已提交
1810
                                for (freevar, place) in freevars.iter().zip(places) {
1811
                                    let var_name = tcx.hir.name(freevar.var_id());
O
Oliver Schneider 已提交
1812
                                    struct_fmt.field(&var_name.as_str(), place);
1813 1814 1815 1816 1817 1818 1819 1820
                                }
                            });

                            struct_fmt.finish()
                        } else {
                            write!(fmt, "[closure]")
                        }
                    }),
J
John Kåre Alsaker 已提交
1821

1822
                    AggregateKind::Generator(def_id, _, _) => ty::tls::with(|tcx| {
J
John Kåre Alsaker 已提交
1823 1824 1825 1826 1827
                        if let Some(node_id) = tcx.hir.as_local_node_id(def_id) {
                            let name = format!("[generator@{:?}]", tcx.hir.span(node_id));
                            let mut struct_fmt = fmt.debug_struct(&name);

                            tcx.with_freevars(node_id, |freevars| {
O
Oliver Schneider 已提交
1828
                                for (freevar, place) in freevars.iter().zip(places) {
1829
                                    let var_name = tcx.hir.name(freevar.var_id());
O
Oliver Schneider 已提交
1830
                                    struct_fmt.field(&var_name.as_str(), place);
J
John Kåre Alsaker 已提交
1831
                                }
O
Oliver Schneider 已提交
1832 1833
                                struct_fmt.field("$state", &places[freevars.len()]);
                                for i in (freevars.len() + 1)..places.len() {
A
Alex Crichton 已提交
1834
                                    struct_fmt.field(&format!("${}", i - freevars.len() - 1),
O
Oliver Schneider 已提交
1835
                                                     &places[i]);
J
John Kåre Alsaker 已提交
1836 1837 1838 1839 1840 1841 1842 1843
                                }
                            });

                            struct_fmt.finish()
                        } else {
                            write!(fmt, "[generator]")
                        }
                    }),
1844 1845
                }
            }
N
Niko Matsakis 已提交
1846 1847 1848 1849 1850
        }
    }
}

///////////////////////////////////////////////////////////////////////////
1851 1852 1853 1854 1855
/// Constants
///
/// Two constants are equal if they are the same constant. Note that
/// this does not necessarily mean that they are "==" in Rust -- in
/// particular one must be wary of `NaN`!
N
Niko Matsakis 已提交
1856

1857
#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
1858 1859 1860
pub struct Constant<'tcx> {
    pub span: Span,
    pub ty: Ty<'tcx>,
1861
    pub literal: Literal<'tcx>,
N
Niko Matsakis 已提交
1862 1863
}

O
Oliver Schneider 已提交
1864 1865
newtype_index!(Promoted { DEBUG_FORMAT = "promoted[{}]" });

1866

1867
#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
1868
pub enum Literal<'tcx> {
1869
    Value {
1870
        value: &'tcx ty::Const<'tcx>,
1871
    },
1872 1873
    Promoted {
        // Index into the `promoted` vector of `Mir`.
1874
        index: Promoted
1875
    },
N
Niko Matsakis 已提交
1876
}
1877 1878

impl<'tcx> Debug for Constant<'tcx> {
1879
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
1880 1881 1882 1883 1884
        write!(fmt, "{:?}", self.literal)
    }
}

impl<'tcx> Debug for Literal<'tcx> {
1885
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
1886 1887
        use self::Literal::*;
        match *self {
1888
            Value { value } => {
J
Jorge Aparicio 已提交
1889
                write!(fmt, "const ")?;
O
Oliver Schneider 已提交
1890
                fmt_const_val(fmt, value)
1891
            }
1892
            Promoted { index } => {
1893
                write!(fmt, "{:?}", index)
1894
            }
1895 1896 1897 1898
        }
    }
}

1899
/// Write a `ConstVal` in a way closer to the original source code than the `Debug` output.
1900 1901
pub fn fmt_const_val<W: Write>(fmt: &mut W, const_val: &ty::Const) -> fmt::Result {
    use middle::const_val::ConstVal;
O
Oliver Schneider 已提交
1902
    match const_val.val {
1903 1904 1905 1906 1907 1908 1909 1910
        ConstVal::Unevaluated(..) => write!(fmt, "{:?}", const_val),
        ConstVal::Value(val) => {
            if let Some(value) = val.to_byval_value() {
                print_miri_value(value, const_val.ty, fmt)
            } else {
                write!(fmt, "{:?}:{}", val, const_val.ty)
            }
        },
O
Oliver Schneider 已提交
1911 1912 1913
    }
}

1914
pub fn print_miri_value<W: Write>(value: Value, ty: Ty, f: &mut W) -> fmt::Result {
O
Oliver Schneider 已提交
1915 1916
    use ty::TypeVariants::*;
    match (value, &ty.sty) {
1917 1918 1919
        (Value::Scalar(Scalar::Bits { bits: 0, .. }), &TyBool) => write!(f, "false"),
        (Value::Scalar(Scalar::Bits { bits: 1, .. }), &TyBool) => write!(f, "true"),
        (Value::Scalar(Scalar::Bits { bits, .. }), &TyFloat(ast::FloatTy::F32)) =>
1920
            write!(f, "{}f32", Single::from_bits(bits)),
1921
        (Value::Scalar(Scalar::Bits { bits, .. }), &TyFloat(ast::FloatTy::F64)) =>
1922
            write!(f, "{}f64", Double::from_bits(bits)),
1923
        (Value::Scalar(Scalar::Bits { bits, .. }), &TyUint(ui)) => write!(f, "{:?}{}", bits, ui),
O
Oliver Schneider 已提交
1924 1925
        (Value::Scalar(Scalar::Bits { bits, .. }), &TyInt(i)) => {
            let bit_width = ty::tls::with(|tcx| {
1926 1927
                 let ty = tcx.lift_to_global(&ty).unwrap();
                 tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size.bits()
O
Oliver Schneider 已提交
1928
            });
1929 1930
            let shift = 128 - bit_width;
            write!(f, "{:?}{}", ((bits as i128) << shift) >> shift, i)
1931
        },
1932
        (Value::Scalar(Scalar::Bits { bits, .. }), &TyChar) =>
1933
            write!(f, "{:?}", ::std::char::from_u32(bits as u32).unwrap()),
1934
        (_, &TyFnDef(did, _)) =>
O
Oliver Schneider 已提交
1935
            write!(f, "{}", item_path_str(did)),
1936
        (Value::ScalarPair(Scalar::Ptr(ptr), Scalar::Bits { bits: len, .. }),
1937
         &TyRef(_, &ty::TyS { sty: TyStr, .. }, _)) => {
O
Oliver Schneider 已提交
1938
            ty::tls::with(|tcx| {
1939 1940 1941 1942 1943 1944 1945 1946 1947
                match tcx.alloc_map.lock().get(ptr.alloc_id) {
                    Some(interpret::AllocType::Memory(alloc)) => {
                        assert_eq!(len as usize as u128, len);
                        let slice = &alloc.bytes[(ptr.offset.bytes() as usize)..][..(len as usize)];
                        let s = ::std::str::from_utf8(slice)
                            .expect("non utf8 str from miri");
                        write!(f, "{:?}", s)
                    }
                    _ => write!(f, "pointer to erroneous constant {:?}, {:?}", ptr, len),
O
Oliver Schneider 已提交
1948
                }
O
Oliver Schneider 已提交
1949 1950 1951
            })
        },
        _ => write!(f, "{:?}:{}", value, ty),
1952 1953
    }
}
1954 1955 1956 1957

fn item_path_str(def_id: DefId) -> String {
    ty::tls::with(|tcx| tcx.item_path_str(def_id))
}
1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974

impl<'tcx> ControlFlowGraph for Mir<'tcx> {

    type Node = BasicBlock;

    fn num_nodes(&self) -> usize { self.basic_blocks.len() }

    fn start_node(&self) -> Self::Node { START_BLOCK }

    fn predecessors<'graph>(&'graph self, node: Self::Node)
                            -> <Self as GraphPredecessors<'graph>>::Iter
    {
        self.predecessors_for(node).clone().into_iter()
    }
    fn successors<'graph>(&'graph self, node: Self::Node)
                          -> <Self as GraphSuccessors<'graph>>::Iter
    {
1975
        self.basic_blocks[node].terminator().successors().cloned()
1976 1977 1978 1979 1980 1981 1982 1983 1984 1985
    }
}

impl<'a, 'b> GraphPredecessors<'b> for Mir<'a> {
    type Item = BasicBlock;
    type Iter = IntoIter<BasicBlock>;
}

impl<'a, 'b>  GraphSuccessors<'b> for Mir<'a> {
    type Item = BasicBlock;
1986
    type Iter = iter::Cloned<Successors<'b>>;
1987
}
1988

1989
#[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
1990 1991 1992 1993
pub struct Location {
    /// the location is within this block
    pub block: BasicBlock,

J
Jay Strict 已提交
1994
    /// the location is the start of the statement; or, if `statement_index`
1995 1996 1997 1998
    /// == num-statements, then the start of the terminator.
    pub statement_index: usize,
}

1999 2000 2001 2002 2003
impl fmt::Debug for Location {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{:?}[{}]", self.block, self.statement_index)
    }
}
2004 2005

impl Location {
N
Niko Matsakis 已提交
2006 2007 2008 2009 2010
    pub const START: Location = Location {
        block: START_BLOCK,
        statement_index: 0,
    };

O
Oliver Schneider 已提交
2011 2012 2013 2014 2015 2016 2017 2018
    /// Returns the location immediately after this one within the enclosing block.
    ///
    /// Note that if this location represents a terminator, then the
    /// resulting location would be out of bounds and invalid.
    pub fn successor_within_block(&self) -> Location {
        Location { block: self.block, statement_index: self.statement_index + 1 }
    }

2019
    pub fn dominates(&self, other: Location, dominators: &Dominators<BasicBlock>) -> bool {
2020 2021 2022 2023 2024 2025 2026
        if self.block == other.block {
            self.statement_index <= other.statement_index
        } else {
            dominators.is_dominated_by(other.block, self.block)
        }
    }
}
2027

O
Oliver Schneider 已提交
2028 2029 2030 2031 2032 2033 2034 2035
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub enum UnsafetyViolationKind {
    General,
    ExternStatic(ast::NodeId),
    BorrowPacked(ast::NodeId),
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
A
Ariel Ben-Yehuda 已提交
2036 2037
pub struct UnsafetyViolation {
    pub source_info: SourceInfo,
O
Oliver Schneider 已提交
2038 2039 2040 2041 2042 2043 2044
    pub description: InternedString,
    pub kind: UnsafetyViolationKind,
}

#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub struct UnsafetyCheckResult {
    /// Violations that are propagated *upwards* from this function
2045
    pub violations: Lrc<[UnsafetyViolation]>,
O
Oliver Schneider 已提交
2046 2047
    /// unsafe blocks in this function, along with whether they are used. This is
    /// used for the "unused_unsafe" lint.
2048
    pub unsafe_blocks: Lrc<[(ast::NodeId, bool)]>,
A
Ariel Ben-Yehuda 已提交
2049 2050
}

J
John Kåre Alsaker 已提交
2051 2052 2053 2054 2055
/// The layout of generator state
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct GeneratorLayout<'tcx> {
    pub fields: Vec<LocalDecl<'tcx>>,
}
2056

2057 2058 2059 2060 2061 2062
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct BorrowCheckResult<'gcx> {
    pub closure_requirements: Option<ClosureRegionRequirements<'gcx>>,
    pub used_mut_upvars: SmallVec<[Field; 8]>,
}

2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080
/// After we borrow check a closure, we are left with various
/// requirements that we have inferred between the free regions that
/// appear in the closure's signature or on its field types.  These
/// requirements are then verified and proved by the closure's
/// creating function. This struct encodes those requirements.
///
/// The requirements are listed as being between various
/// `RegionVid`. The 0th region refers to `'static`; subsequent region
/// vids refer to the free regions that appear in the closure (or
/// generator's) type, in order of appearance. (This numbering is
/// actually defined by the `UniversalRegions` struct in the NLL
/// region checker. See for example
/// `UniversalRegions::closure_mapping`.) Note that we treat the free
/// regions in the closure's type "as if" they were erased, so their
/// precise identity is not important, only their position.
///
/// Example: If type check produces a closure with the closure substs:
///
C
Clar Charr 已提交
2081
/// ```text
2082 2083 2084 2085 2086 2087 2088 2089
/// ClosureSubsts = [
///     i8,                                  // the "closure kind"
///     for<'x> fn(&'a &'x u32) -> &'x u32,  // the "closure signature"
///     &'a String,                          // some upvar
/// ]
/// ```
///
/// here, there is one unique free region (`'a`) but it appears
2090
/// twice. We would "renumber" each occurrence to a unique vid, as follows:
2091
///
C
Clar Charr 已提交
2092
/// ```text
2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103
/// ClosureSubsts = [
///     i8,                                  // the "closure kind"
///     for<'x> fn(&'1 &'x u32) -> &'x u32,  // the "closure signature"
///     &'2 String,                          // some upvar
/// ]
/// ```
///
/// Now the code might impose a requirement like `'1: '2`. When an
/// instance of the closure is created, the corresponding free regions
/// can be extracted from its type and constrained to have the given
/// outlives relationship.
2104 2105 2106 2107 2108 2109 2110 2111 2112
///
/// In some cases, we have to record outlives requirements between
/// types and regions as well. In that case, if those types include
/// any regions, those regions are recorded as `ReClosureBound`
/// instances assigned one of these same indices. Those regions will
/// be substituted away by the creator. We use `ReClosureBound` in
/// that case because the regions must be allocated in the global
/// TyCtxt, and hence we cannot use `ReVar` (which is what we use
/// internally within the rest of the NLL code).
M
Michael Woerister 已提交
2113
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
2114
pub struct ClosureRegionRequirements<'gcx> {
2115 2116 2117 2118 2119 2120 2121 2122 2123
    /// The number of external regions defined on the closure.  In our
    /// example above, it would be 3 -- one for `'static`, then `'1`
    /// and `'2`. This is just used for a sanity check later on, to
    /// make sure that the number of regions we see at the callsite
    /// matches.
    pub num_external_vids: usize,

    /// Requirements between the various free regions defined in
    /// indices.
2124
    pub outlives_requirements: Vec<ClosureOutlivesRequirement<'gcx>>,
2125 2126
}

2127 2128 2129 2130 2131 2132
/// Indicates an outlives constraint between a type or between two
/// free-regions declared on the closure.
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct ClosureOutlivesRequirement<'tcx> {
    // This region or type ...
    pub subject: ClosureOutlivesSubject<'tcx>,
2133 2134 2135 2136 2137 2138 2139 2140

    // .. must outlive this one.
    pub outlived_free_region: ty::RegionVid,

    // If not, report an error here.
    pub blame_span: Span,
}

2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157
/// The subject of a ClosureOutlivesRequirement -- that is, the thing
/// that must outlive some region.
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
pub enum ClosureOutlivesSubject<'tcx> {
    /// Subject is a type, typically a type parameter, but could also
    /// be a projection. Indicates a requirement like `T: 'a` being
    /// passed to the caller, where the type here is `T`.
    ///
    /// The type here is guaranteed not to contain any free regions at
    /// present.
    Ty(Ty<'tcx>),

    /// Subject is a free region from the closure. Indicates a requirement
    /// like `'a: 'b` being passed to the caller; the region here is `'a`.
    Region(ty::RegionVid),
}

2158 2159 2160 2161
/*
 * TypeFoldable implementations for MIR types
 */

2162 2163 2164 2165 2166
CloneTypeFoldableAndLiftImpls! {
    Mutability,
    SourceInfo,
    UpvarDecl,
    ValidationOp,
2167
    SourceScope,
2168 2169
    SourceScopeData,
    SourceScopeLocalData,
2170 2171
}

2172 2173 2174
BraceStructTypeFoldableImpl! {
    impl<'tcx> TypeFoldable<'tcx> for Mir<'tcx> {
        basic_blocks,
2175
        source_scopes,
2176
        source_scope_local_data,
2177 2178 2179 2180 2181 2182 2183 2184 2185 2186
        promoted,
        yield_ty,
        generator_drop,
        generator_layout,
        local_decls,
        arg_count,
        upvar_decls,
        spread_arg,
        span,
        cache,
J
John Kåre Alsaker 已提交
2187 2188 2189
    }
}

2190 2191 2192
BraceStructTypeFoldableImpl! {
    impl<'tcx> TypeFoldable<'tcx> for GeneratorLayout<'tcx> {
        fields
2193 2194 2195
    }
}

2196 2197 2198 2199 2200 2201 2202
BraceStructTypeFoldableImpl! {
    impl<'tcx> TypeFoldable<'tcx> for LocalDecl<'tcx> {
        mutability,
        is_user_variable,
        internal,
        ty,
        name,
2203
        syntactic_source_info,
2204
        visibility_source_info,
2205
    }
2206
}
2207

2208 2209 2210 2211 2212
BraceStructTypeFoldableImpl! {
    impl<'tcx> TypeFoldable<'tcx> for BasicBlockData<'tcx> {
        statements,
        terminator,
        is_cleanup,
2213 2214 2215
    }
}

2216 2217 2218
BraceStructTypeFoldableImpl! {
    impl<'tcx> TypeFoldable<'tcx> for ValidationOperand<'tcx, Place<'tcx>> {
        place, ty, re, mutbl
2219
    }
2220
}
2221

2222 2223 2224
BraceStructTypeFoldableImpl! {
    impl<'tcx> TypeFoldable<'tcx> for Statement<'tcx> {
        source_info, kind
2225 2226 2227
    }
}

2228 2229 2230
EnumTypeFoldableImpl! {
    impl<'tcx> TypeFoldable<'tcx> for StatementKind<'tcx> {
        (StatementKind::Assign)(a, b),
2231
        (StatementKind::ReadForMatch)(place),
2232 2233 2234 2235 2236 2237
        (StatementKind::SetDiscriminant) { place, variant_index },
        (StatementKind::StorageLive)(a),
        (StatementKind::StorageDead)(a),
        (StatementKind::InlineAsm) { asm, outputs, inputs },
        (StatementKind::Validate)(a, b),
        (StatementKind::EndRegion)(a),
D
David Wood 已提交
2238
        (StatementKind::UserAssertTy)(a, b),
2239
        (StatementKind::Nop),
2240
    }
2241
}
2242

2243 2244 2245 2246 2247
EnumTypeFoldableImpl! {
    impl<'tcx, T> TypeFoldable<'tcx> for ClearCrossCrate<T> {
        (ClearCrossCrate::Clear),
        (ClearCrossCrate::Set)(a),
    } where T: TypeFoldable<'tcx>
2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263
}

impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
        use mir::TerminatorKind::*;

        let kind = match self.kind {
            Goto { target } => Goto { target: target },
            SwitchInt { ref discr, switch_ty, ref values, ref targets } => SwitchInt {
                discr: discr.fold_with(folder),
                switch_ty: switch_ty.fold_with(folder),
                values: values.clone(),
                targets: targets.clone()
            },
            Drop { ref location, target, unwind } => Drop {
                location: location.fold_with(folder),
2264 2265
                target,
                unwind,
2266 2267 2268 2269
            },
            DropAndReplace { ref location, ref value, target, unwind } => DropAndReplace {
                location: location.fold_with(folder),
                value: value.fold_with(folder),
2270 2271
                target,
                unwind,
2272
            },
J
John Kåre Alsaker 已提交
2273
            Yield { ref value, resume, drop } => Yield {
J
John Kåre Alsaker 已提交
2274 2275 2276 2277
                value: value.fold_with(folder),
                resume: resume,
                drop: drop,
            },
2278 2279 2280 2281 2282 2283 2284 2285 2286
            Call { ref func, ref args, ref destination, cleanup } => {
                let dest = destination.as_ref().map(|&(ref loc, dest)| {
                    (loc.fold_with(folder), dest)
                });

                Call {
                    func: func.fold_with(folder),
                    args: args.fold_with(folder),
                    destination: dest,
2287
                    cleanup,
2288 2289 2290
                }
            },
            Assert { ref cond, expected, ref msg, target, cleanup } => {
2291 2292
                let msg = if let EvalErrorKind::BoundsCheck { ref len, ref index } = *msg {
                    EvalErrorKind::BoundsCheck {
2293 2294 2295 2296 2297 2298 2299 2300
                        len: len.fold_with(folder),
                        index: index.fold_with(folder),
                    }
                } else {
                    msg.clone()
                };
                Assert {
                    cond: cond.fold_with(folder),
2301 2302 2303 2304
                    expected,
                    msg,
                    target,
                    cleanup,
2305 2306
                }
            },
J
John Kåre Alsaker 已提交
2307
            GeneratorDrop => GeneratorDrop,
2308
            Resume => Resume,
D
David Henningsson 已提交
2309
            Abort => Abort,
2310 2311
            Return => Return,
            Unreachable => Unreachable,
O
Oliver Schneider 已提交
2312
            FalseEdges { real_target, ref imaginary_targets } =>
2313 2314
                FalseEdges { real_target, imaginary_targets: imaginary_targets.clone() },
            FalseUnwind { real_target, unwind } => FalseUnwind { real_target, unwind },
2315 2316 2317
        };
        Terminator {
            source_info: self.source_info,
2318
            kind,
2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330
        }
    }

    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
        use mir::TerminatorKind::*;

        match self.kind {
            SwitchInt { ref discr, switch_ty, .. } =>
                discr.visit_with(visitor) || switch_ty.visit_with(visitor),
            Drop { ref location, ..} => location.visit_with(visitor),
            DropAndReplace { ref location, ref value, ..} =>
                location.visit_with(visitor) || value.visit_with(visitor),
J
John Kåre Alsaker 已提交
2331
            Yield { ref value, ..} =>
J
John Kåre Alsaker 已提交
2332
                value.visit_with(visitor),
2333 2334 2335 2336 2337 2338 2339 2340
            Call { ref func, ref args, ref destination, .. } => {
                let dest = if let Some((ref loc, _)) = *destination {
                    loc.visit_with(visitor)
                } else { false };
                dest || func.visit_with(visitor) || args.visit_with(visitor)
            },
            Assert { ref cond, ref msg, .. } => {
                if cond.visit_with(visitor) {
2341
                    if let EvalErrorKind::BoundsCheck { ref len, ref index } = *msg {
2342 2343 2344 2345 2346 2347 2348 2349 2350 2351
                        len.visit_with(visitor) || index.visit_with(visitor)
                    } else {
                        false
                    }
                } else {
                    false
                }
            },
            Goto { .. } |
            Resume |
D
David Henningsson 已提交
2352
            Abort |
2353
            Return |
J
John Kåre Alsaker 已提交
2354
            GeneratorDrop |
O
Oliver Schneider 已提交
2355
            Unreachable |
2356 2357
            FalseEdges { .. } |
            FalseUnwind { .. } => false
2358 2359 2360 2361
        }
    }
}

O
Oliver Schneider 已提交
2362
impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> {
2363 2364
    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
        match self {
O
Oliver Schneider 已提交
2365
            &Place::Projection(ref p) => Place::Projection(p.fold_with(folder)),
2366 2367 2368 2369 2370
            _ => self.clone()
        }
    }

    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
O
Oliver Schneider 已提交
2371
        if let &Place::Projection(ref p) = self {
2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384
            p.visit_with(visitor)
        } else {
            false
        }
    }
}

impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
        use mir::Rvalue::*;
        match *self {
            Use(ref op) => Use(op.fold_with(folder)),
            Repeat(ref op, len) => Repeat(op.fold_with(folder), len),
O
Oliver Schneider 已提交
2385 2386 2387
            Ref(region, bk, ref place) =>
                Ref(region.fold_with(folder), bk, place.fold_with(folder)),
            Len(ref place) => Len(place.fold_with(folder)),
2388 2389 2390 2391 2392 2393
            Cast(kind, ref op, ty) => Cast(kind, op.fold_with(folder), ty.fold_with(folder)),
            BinaryOp(op, ref rhs, ref lhs) =>
                BinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder)),
            CheckedBinaryOp(op, ref rhs, ref lhs) =>
                CheckedBinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder)),
            UnaryOp(op, ref val) => UnaryOp(op, val.fold_with(folder)),
O
Oliver Schneider 已提交
2394
            Discriminant(ref place) => Discriminant(place.fold_with(folder)),
2395
            NullaryOp(op, ty) => NullaryOp(op, ty.fold_with(folder)),
2396
            Aggregate(ref kind, ref fields) => {
A
Ariel Ben-Yehuda 已提交
2397
                let kind = box match **kind {
2398 2399 2400 2401 2402
                    AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)),
                    AggregateKind::Tuple => AggregateKind::Tuple,
                    AggregateKind::Adt(def, v, substs, n) =>
                        AggregateKind::Adt(def, v, substs.fold_with(folder), n),
                    AggregateKind::Closure(id, substs) =>
J
John Kåre Alsaker 已提交
2403
                        AggregateKind::Closure(id, substs.fold_with(folder)),
2404 2405
                    AggregateKind::Generator(id, substs, movablity) =>
                        AggregateKind::Generator(id, substs.fold_with(folder), movablity),
2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416
                };
                Aggregate(kind, fields.fold_with(folder))
            }
        }
    }

    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
        use mir::Rvalue::*;
        match *self {
            Use(ref op) => op.visit_with(visitor),
            Repeat(ref op, _) => op.visit_with(visitor),
O
Oliver Schneider 已提交
2417 2418
            Ref(region, _, ref place) => region.visit_with(visitor) || place.visit_with(visitor),
            Len(ref place) => place.visit_with(visitor),
2419 2420 2421 2422 2423
            Cast(_, ref op, ty) => op.visit_with(visitor) || ty.visit_with(visitor),
            BinaryOp(_, ref rhs, ref lhs) |
            CheckedBinaryOp(_, ref rhs, ref lhs) =>
                rhs.visit_with(visitor) || lhs.visit_with(visitor),
            UnaryOp(_, ref val) => val.visit_with(visitor),
O
Oliver Schneider 已提交
2424
            Discriminant(ref place) => place.visit_with(visitor),
2425
            NullaryOp(_, ty) => ty.visit_with(visitor),
2426
            Aggregate(ref kind, ref fields) => {
A
Ariel Ben-Yehuda 已提交
2427
                (match **kind {
2428 2429 2430
                    AggregateKind::Array(ty) => ty.visit_with(visitor),
                    AggregateKind::Tuple => false,
                    AggregateKind::Adt(_, _, substs, _) => substs.visit_with(visitor),
J
John Kåre Alsaker 已提交
2431
                    AggregateKind::Closure(_, substs) => substs.visit_with(visitor),
2432
                    AggregateKind::Generator(_, substs, _) => substs.visit_with(visitor),
2433 2434 2435 2436 2437 2438 2439 2440 2441
                }) || fields.visit_with(visitor)
            }
        }
    }
}

impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> {
    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
        match *self {
O
Oliver Schneider 已提交
2442 2443
            Operand::Copy(ref place) => Operand::Copy(place.fold_with(folder)),
            Operand::Move(ref place) => Operand::Move(place.fold_with(folder)),
2444 2445 2446 2447 2448 2449
            Operand::Constant(ref c) => Operand::Constant(c.fold_with(folder)),
        }
    }

    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
        match *self {
O
Oliver Schneider 已提交
2450 2451
            Operand::Copy(ref place) |
            Operand::Move(ref place) => place.visit_with(visitor),
2452 2453 2454 2455 2456
            Operand::Constant(ref c) => c.visit_with(visitor)
        }
    }
}

2457 2458
impl<'tcx, B, V, T> TypeFoldable<'tcx> for Projection<'tcx, B, V, T>
    where B: TypeFoldable<'tcx>, V: TypeFoldable<'tcx>, T: TypeFoldable<'tcx>
2459 2460 2461 2462 2463 2464 2465
{
    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
        use mir::ProjectionElem::*;

        let base = self.base.fold_with(folder);
        let elem = match self.elem {
            Deref => Deref,
2466
            Field(f, ref ty) => Field(f, ty.fold_with(folder)),
2467 2468 2469 2470 2471
            Index(ref v) => Index(v.fold_with(folder)),
            ref elem => elem.clone()
        };

        Projection {
2472 2473
            base,
            elem,
2474 2475 2476 2477 2478 2479 2480 2481
        }
    }

    fn super_visit_with<Vs: TypeVisitor<'tcx>>(&self, visitor: &mut Vs) -> bool {
        use mir::ProjectionElem::*;

        self.base.visit_with(visitor) ||
            match self.elem {
2482
                Field(_, ref ty) => ty.visit_with(visitor),
2483 2484 2485 2486 2487 2488
                Index(ref v) => v.visit_with(visitor),
                _ => false
            }
    }
}

O
Oliver Schneider 已提交
2489 2490 2491 2492 2493 2494 2495 2496 2497
impl<'tcx> TypeFoldable<'tcx> for Field {
    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, _: &mut F) -> Self {
        *self
    }
    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> bool {
        false
    }
}

2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513
impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> {
    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
        Constant {
            span: self.span.clone(),
            ty: self.ty.fold_with(folder),
            literal: self.literal.fold_with(folder)
        }
    }
    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
        self.ty.visit_with(visitor) || self.literal.visit_with(visitor)
    }
}

impl<'tcx> TypeFoldable<'tcx> for Literal<'tcx> {
    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
        match *self {
2514 2515
            Literal::Value { value } => Literal::Value {
                value: value.fold_with(folder)
2516
            },
2517
            Literal::Promoted { index } => Literal::Promoted { index }
2518 2519 2520 2521
        }
    }
    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
        match *self {
2522 2523
            Literal::Value { value } => value.visit_with(visitor),
            Literal::Promoted { .. } => false
2524 2525 2526
        }
    }
}