about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOliver Schneider <git-no-reply-9879165716479413131@oli-obk.de>2017-12-27 21:32:01 +0100
committerOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>2018-03-08 08:08:14 +0100
commite97089dae33d5b228bb1b50ae12e96b13ab499b3 (patch)
tree8746e6ce819ca68f421ff661278eb48fd40dc27c
parent918b6d763319863fb53c5b7bceebc14ad5fb4024 (diff)
downloadrust-e97089dae33d5b228bb1b50ae12e96b13ab499b3.tar.gz
rust-e97089dae33d5b228bb1b50ae12e96b13ab499b3.zip
Move librustc_const_eval to librustc_mir
-rw-r--r--src/doc/rustc-ux-guidelines.md1
-rw-r--r--src/librustc/dep_graph/dep_node.rs1
-rw-r--r--src/librustc/ty/maps/config.rs1
-rw-r--r--src/librustc_const_eval/Cargo.toml19
-rw-r--r--src/librustc_const_eval/diagnostics.rs571
-rw-r--r--src/librustc_driver/Cargo.toml1
-rw-r--r--src/librustc_driver/driver.rs3
-rw-r--r--src/librustc_driver/lib.rs2
-rw-r--r--src/librustc_lint/Cargo.toml2
-rw-r--r--src/librustc_lint/lib.rs2
-rw-r--r--src/librustc_lint/types.rs2
-rw-r--r--src/librustc_mir/Cargo.toml2
-rw-r--r--src/librustc_mir/build/mod.rs2
-rw-r--r--src/librustc_mir/const_eval/_match.rs (renamed from src/librustc_const_eval/_match.rs)6
-rw-r--r--src/librustc_mir/const_eval/check_match.rs (renamed from src/librustc_const_eval/check_match.rs)8
-rw-r--r--src/librustc_mir/const_eval/eval.rs (renamed from src/librustc_const_eval/eval.rs)0
-rw-r--r--src/librustc_mir/const_eval/mod.rs18
-rw-r--r--src/librustc_mir/const_eval/pattern.rs (renamed from src/librustc_const_eval/pattern.rs)29
-rw-r--r--src/librustc_mir/diagnostics.rs550
-rw-r--r--src/librustc_mir/hair/mod.rs2
-rw-r--r--src/librustc_mir/interpret/const_eval.rs34
-rw-r--r--src/librustc_mir/lib.rs6
-rw-r--r--src/librustc_passes/Cargo.toml2
-rw-r--r--src/librustc_passes/consts.rs2
-rw-r--r--src/librustc_passes/lib.rs2
25 files changed, 626 insertions, 642 deletions
diff --git a/src/doc/rustc-ux-guidelines.md b/src/doc/rustc-ux-guidelines.md
index 323d49e4691..b62762ef69e 100644
--- a/src/doc/rustc-ux-guidelines.md
+++ b/src/doc/rustc-ux-guidelines.md
@@ -64,7 +64,6 @@ for details on how to format and write long error codes.
   [librustc](https://github.com/rust-lang/rust/blob/master/src/librustc/diagnostics.rs),
   [libsyntax](https://github.com/rust-lang/rust/blob/master/src/libsyntax/diagnostics.rs),
   [librustc_borrowck](https://github.com/rust-lang/rust/blob/master/src/librustc_borrowck/diagnostics.rs),
-  [librustc_const_eval](https://github.com/rust-lang/rust/blob/master/src/librustc_const_eval/diagnostics.rs),
   [librustc_metadata](https://github.com/rust-lang/rust/blob/master/src/librustc_metadata/diagnostics.rs),
   [librustc_mir](https://github.com/rust-lang/rust/blob/master/src/librustc_mir/diagnostics.rs),
   [librustc_passes](https://github.com/rust-lang/rust/blob/master/src/librustc_passes/diagnostics.rs),
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index 15e1d38be69..ed46296389d 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -63,7 +63,6 @@
 use hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX};
 use hir::map::DefPathHash;
 use hir::{HirId, ItemLocalId};
-use mir;
 
 use ich::Fingerprint;
 use ty::{TyCtxt, Instance, InstanceDef, ParamEnv, ParamEnvAnd, PolyTraitRef, Ty};
diff --git a/src/librustc/ty/maps/config.rs b/src/librustc/ty/maps/config.rs
index ef1c8a8d4fa..d880b022e2f 100644
--- a/src/librustc/ty/maps/config.rs
+++ b/src/librustc/ty/maps/config.rs
@@ -13,7 +13,6 @@ use hir::def_id::{CrateNum, DefId, DefIndex};
 use ty::{self, Ty, TyCtxt};
 use ty::maps::queries;
 use ty::subst::Substs;
-use mir;
 
 use std::hash::Hash;
 use syntax_pos::symbol::InternedString;
diff --git a/src/librustc_const_eval/Cargo.toml b/src/librustc_const_eval/Cargo.toml
deleted file mode 100644
index 53b8402ab2a..00000000000
--- a/src/librustc_const_eval/Cargo.toml
+++ /dev/null
@@ -1,19 +0,0 @@
-[package]
-authors = ["The Rust Project Developers"]
-name = "rustc_const_eval"
-version = "0.0.0"
-
-[lib]
-name = "rustc_const_eval"
-path = "lib.rs"
-crate-type = ["dylib"]
-
-[dependencies]
-arena = { path = "../libarena" }
-log = "0.4"
-rustc = { path = "../librustc" }
-rustc_const_math = { path = "../librustc_const_math" }
-rustc_data_structures = { path = "../librustc_data_structures" }
-rustc_errors = { path = "../librustc_errors" }
-syntax = { path = "../libsyntax" }
-syntax_pos = { path = "../libsyntax_pos" }
diff --git a/src/librustc_const_eval/diagnostics.rs b/src/librustc_const_eval/diagnostics.rs
deleted file mode 100644
index d01b3c45f7f..00000000000
--- a/src/librustc_const_eval/diagnostics.rs
+++ /dev/null
@@ -1,571 +0,0 @@
-// 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.
-
-#![allow(non_snake_case)]
-
-// Error messages for EXXXX errors.
-// Each message should start and end with a new line, and be wrapped to 80 characters.
-// In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use `:set tw=0` to disable.
-register_long_diagnostics! {
-
-E0001: r##"
-#### Note: this error code is no longer emitted by the compiler.
-
-This error suggests that the expression arm corresponding to the noted pattern
-will never be reached as for all possible values of the expression being
-matched, one of the preceding patterns will match.
-
-This means that perhaps some of the preceding patterns are too general, this
-one is too specific or the ordering is incorrect.
-
-For example, the following `match` block has too many arms:
-
-```
-match Some(0) {
-    Some(bar) => {/* ... */}
-    x => {/* ... */} // This handles the `None` case
-    _ => {/* ... */} // All possible cases have already been handled
-}
-```
-
-`match` blocks have their patterns matched in order, so, for example, putting
-a wildcard arm above a more specific arm will make the latter arm irrelevant.
-
-Ensure the ordering of the match arm is correct and remove any superfluous
-arms.
-"##,
-
-E0002: r##"
-#### Note: this error code is no longer emitted by the compiler.
-
-This error indicates that an empty match expression is invalid because the type
-it is matching on is non-empty (there exist values of this type). In safe code
-it is impossible to create an instance of an empty type, so empty match
-expressions are almost never desired. This error is typically fixed by adding
-one or more cases to the match expression.
-
-An example of an empty type is `enum Empty { }`. So, the following will work:
-
-```
-enum Empty {}
-
-fn foo(x: Empty) {
-    match x {
-        // empty
-    }
-}
-```
-
-However, this won't:
-
-```compile_fail
-fn foo(x: Option<String>) {
-    match x {
-        // empty
-    }
-}
-```
-"##,
-
-E0003: r##"
-#### Note: this error code is no longer emitted by the compiler.
-
-Not-a-Number (NaN) values cannot be compared for equality and hence can never
-match the input to a match expression. So, the following will not compile:
-
-```compile_fail
-const NAN: f32 = 0.0 / 0.0;
-
-let number = 0.1f32;
-
-match number {
-    NAN => { /* ... */ },
-    _ => {}
-}
-```
-
-To match against NaN values, you should instead use the `is_nan()` method in a
-guard, like so:
-
-```
-let number = 0.1f32;
-
-match number {
-    x if x.is_nan() => { /* ... */ }
-    _ => {}
-}
-```
-"##,
-
-E0004: r##"
-This error indicates that the compiler cannot guarantee a matching pattern for
-one or more possible inputs to a match expression. Guaranteed matches are
-required in order to assign values to match expressions, or alternatively,
-determine the flow of execution. Erroneous code example:
-
-```compile_fail,E0004
-enum Terminator {
-    HastaLaVistaBaby,
-    TalkToMyHand,
-}
-
-let x = Terminator::HastaLaVistaBaby;
-
-match x { // error: non-exhaustive patterns: `HastaLaVistaBaby` not covered
-    Terminator::TalkToMyHand => {}
-}
-```
-
-If you encounter this error you must alter your patterns so that every possible
-value of the input type is matched. For types with a small number of variants
-(like enums) you should probably cover all cases explicitly. Alternatively, the
-underscore `_` wildcard pattern can be added after all other patterns to match
-"anything else". Example:
-
-```
-enum Terminator {
-    HastaLaVistaBaby,
-    TalkToMyHand,
-}
-
-let x = Terminator::HastaLaVistaBaby;
-
-match x {
-    Terminator::TalkToMyHand => {}
-    Terminator::HastaLaVistaBaby => {}
-}
-
-// or:
-
-match x {
-    Terminator::TalkToMyHand => {}
-    _ => {}
-}
-```
-"##,
-
-E0005: r##"
-Patterns used to bind names must be irrefutable, that is, they must guarantee
-that a name will be extracted in all cases. Erroneous code example:
-
-```compile_fail,E0005
-let x = Some(1);
-let Some(y) = x;
-// error: refutable pattern in local binding: `None` not covered
-```
-
-If you encounter this error you probably need to use a `match` or `if let` to
-deal with the possibility of failure. Example:
-
-```
-let x = Some(1);
-
-match x {
-    Some(y) => {
-        // do something
-    },
-    None => {}
-}
-
-// or:
-
-if let Some(y) = x {
-    // do something
-}
-```
-"##,
-
-E0007: r##"
-This error indicates that the bindings in a match arm would require a value to
-be moved into more than one location, thus violating unique ownership. Code
-like the following is invalid as it requires the entire `Option<String>` to be
-moved into a variable called `op_string` while simultaneously requiring the
-inner `String` to be moved into a variable called `s`.
-
-```compile_fail,E0007
-let x = Some("s".to_string());
-
-match x {
-    op_string @ Some(s) => {}, // error: cannot bind by-move with sub-bindings
-    None => {},
-}
-```
-
-See also the error E0303.
-"##,
-
-E0008: r##"
-Names bound in match arms retain their type in pattern guards. As such, if a
-name is bound by move in a pattern, it should also be moved to wherever it is
-referenced in the pattern guard code. Doing so however would prevent the name
-from being available in the body of the match arm. Consider the following:
-
-```compile_fail,E0008
-match Some("hi".to_string()) {
-    Some(s) if s.len() == 0 => {}, // use s.
-    _ => {},
-}
-```
-
-The variable `s` has type `String`, and its use in the guard is as a variable of
-type `String`. The guard code effectively executes in a separate scope to the
-body of the arm, so the value would be moved into this anonymous scope and
-therefore becomes unavailable in the body of the arm.
-
-The problem above can be solved by using the `ref` keyword.
-
-```
-match Some("hi".to_string()) {
-    Some(ref s) if s.len() == 0 => {},
-    _ => {},
-}
-```
-
-Though this example seems innocuous and easy to solve, the problem becomes clear
-when it encounters functions which consume the value:
-
-```compile_fail,E0008
-struct A{}
-
-impl A {
-    fn consume(self) -> usize {
-        0
-    }
-}
-
-fn main() {
-    let a = Some(A{});
-    match a {
-        Some(y) if y.consume() > 0 => {}
-        _ => {}
-    }
-}
-```
-
-In this situation, even the `ref` keyword cannot solve it, since borrowed
-content cannot be moved. This problem cannot be solved generally. If the value
-can be cloned, here is a not-so-specific solution:
-
-```
-#[derive(Clone)]
-struct A{}
-
-impl A {
-    fn consume(self) -> usize {
-        0
-    }
-}
-
-fn main() {
-    let a = Some(A{});
-    match a{
-        Some(ref y) if y.clone().consume() > 0 => {}
-        _ => {}
-    }
-}
-```
-
-If the value will be consumed in the pattern guard, using its clone will not
-move its ownership, so the code works.
-"##,
-
-E0009: r##"
-In a pattern, all values that don't implement the `Copy` trait have to be bound
-the same way. The goal here is to avoid binding simultaneously by-move and
-by-ref.
-
-This limitation may be removed in a future version of Rust.
-
-Erroneous code example:
-
-```compile_fail,E0009
-struct X { x: (), }
-
-let x = Some((X { x: () }, X { x: () }));
-match x {
-    Some((y, ref z)) => {}, // error: cannot bind by-move and by-ref in the
-                            //        same pattern
-    None => panic!()
-}
-```
-
-You have two solutions:
-
-Solution #1: Bind the pattern's values the same way.
-
-```
-struct X { x: (), }
-
-let x = Some((X { x: () }, X { x: () }));
-match x {
-    Some((ref y, ref z)) => {},
-    // or Some((y, z)) => {}
-    None => panic!()
-}
-```
-
-Solution #2: Implement the `Copy` trait for the `X` structure.
-
-However, please keep in mind that the first solution should be preferred.
-
-```
-#[derive(Clone, Copy)]
-struct X { x: (), }
-
-let x = Some((X { x: () }, X { x: () }));
-match x {
-    Some((y, ref z)) => {},
-    None => panic!()
-}
-```
-"##,
-
-E0158: r##"
-`const` and `static` mean different things. A `const` is a compile-time
-constant, an alias for a literal value. This property means you can match it
-directly within a pattern.
-
-The `static` keyword, on the other hand, guarantees a fixed location in memory.
-This does not always mean that the value is constant. For example, a global
-mutex can be declared `static` as well.
-
-If you want to match against a `static`, consider using a guard instead:
-
-```
-static FORTY_TWO: i32 = 42;
-
-match Some(42) {
-    Some(x) if x == FORTY_TWO => {}
-    _ => {}
-}
-```
-"##,
-
-E0162: r##"
-An if-let pattern attempts to match the pattern, and enters the body if the
-match was successful. If the match is irrefutable (when it cannot fail to
-match), use a regular `let`-binding instead. For instance:
-
-```compile_fail,E0162
-struct Irrefutable(i32);
-let irr = Irrefutable(0);
-
-// This fails to compile because the match is irrefutable.
-if let Irrefutable(x) = irr {
-    // This body will always be executed.
-    // ...
-}
-```
-
-Try this instead:
-
-```
-struct Irrefutable(i32);
-let irr = Irrefutable(0);
-
-let Irrefutable(x) = irr;
-println!("{}", x);
-```
-"##,
-
-E0165: r##"
-A while-let pattern attempts to match the pattern, and enters the body if the
-match was successful. If the match is irrefutable (when it cannot fail to
-match), use a regular `let`-binding inside a `loop` instead. For instance:
-
-```compile_fail,E0165
-struct Irrefutable(i32);
-let irr = Irrefutable(0);
-
-// This fails to compile because the match is irrefutable.
-while let Irrefutable(x) = irr {
-    // ...
-}
-```
-
-Try this instead:
-
-```no_run
-struct Irrefutable(i32);
-let irr = Irrefutable(0);
-
-loop {
-    let Irrefutable(x) = irr;
-    // ...
-}
-```
-"##,
-
-E0170: r##"
-Enum variants are qualified by default. For example, given this type:
-
-```
-enum Method {
-    GET,
-    POST,
-}
-```
-
-You would match it using:
-
-```
-enum Method {
-    GET,
-    POST,
-}
-
-let m = Method::GET;
-
-match m {
-    Method::GET => {},
-    Method::POST => {},
-}
-```
-
-If you don't qualify the names, the code will bind new variables named "GET" and
-"POST" instead. This behavior is likely not what you want, so `rustc` warns when
-that happens.
-
-Qualified names are good practice, and most code works well with them. But if
-you prefer them unqualified, you can import the variants into scope:
-
-```
-use Method::*;
-enum Method { GET, POST }
-# fn main() {}
-```
-
-If you want others to be able to import variants from your module directly, use
-`pub use`:
-
-```
-pub use Method::*;
-pub enum Method { GET, POST }
-# fn main() {}
-```
-"##,
-
-
-E0297: r##"
-#### Note: this error code is no longer emitted by the compiler.
-
-Patterns used to bind names must be irrefutable. That is, they must guarantee
-that a name will be extracted in all cases. Instead of pattern matching the
-loop variable, consider using a `match` or `if let` inside the loop body. For
-instance:
-
-```compile_fail,E0005
-let xs : Vec<Option<i32>> = vec![Some(1), None];
-
-// This fails because `None` is not covered.
-for Some(x) in xs {
-    // ...
-}
-```
-
-Match inside the loop instead:
-
-```
-let xs : Vec<Option<i32>> = vec![Some(1), None];
-
-for item in xs {
-    match item {
-        Some(x) => {},
-        None => {},
-    }
-}
-```
-
-Or use `if let`:
-
-```
-let xs : Vec<Option<i32>> = vec![Some(1), None];
-
-for item in xs {
-    if let Some(x) = item {
-        // ...
-    }
-}
-```
-"##,
-
-E0301: r##"
-Mutable borrows are not allowed in pattern guards, because matching cannot have
-side effects. Side effects could alter the matched object or the environment
-on which the match depends in such a way, that the match would not be
-exhaustive. For instance, the following would not match any arm if mutable
-borrows were allowed:
-
-```compile_fail,E0301
-match Some(()) {
-    None => { },
-    option if option.take().is_none() => {
-        /* impossible, option is `Some` */
-    },
-    Some(_) => { } // When the previous match failed, the option became `None`.
-}
-```
-"##,
-
-E0302: r##"
-Assignments are not allowed in pattern guards, because matching cannot have
-side effects. Side effects could alter the matched object or the environment
-on which the match depends in such a way, that the match would not be
-exhaustive. For instance, the following would not match any arm if assignments
-were allowed:
-
-```compile_fail,E0302
-match Some(()) {
-    None => { },
-    option if { option = None; false } => { },
-    Some(_) => { } // When the previous match failed, the option became `None`.
-}
-```
-"##,
-
-E0303: r##"
-In certain cases it is possible for sub-bindings to violate memory safety.
-Updates to the borrow checker in a future version of Rust may remove this
-restriction, but for now patterns must be rewritten without sub-bindings.
-
-Before:
-
-```compile_fail,E0303
-match Some("hi".to_string()) {
-    ref op_string_ref @ Some(s) => {},
-    None => {},
-}
-```
-
-After:
-
-```
-match Some("hi".to_string()) {
-    Some(ref s) => {
-        let op_string_ref = &Some(s);
-        // ...
-    },
-    None => {},
-}
-```
-
-The `op_string_ref` binding has type `&Option<&String>` in both cases.
-
-See also https://github.com/rust-lang/rust/issues/14587
-"##,
-
-}
-
-
-register_diagnostics! {
-//  E0298, // cannot compare constants
-//  E0299, // mismatched types between arms
-//  E0471, // constant evaluation error (in pattern)
-}
diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml
index 802fe61d6f3..6a1d9e56534 100644
--- a/src/librustc_driver/Cargo.toml
+++ b/src/librustc_driver/Cargo.toml
@@ -17,7 +17,6 @@ rustc = { path = "../librustc" }
 rustc_allocator = { path = "../librustc_allocator" }
 rustc_back = { path = "../librustc_back" }
 rustc_borrowck = { path = "../librustc_borrowck" }
-rustc_const_eval = { path = "../librustc_const_eval" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
 rustc_incremental = { path = "../librustc_incremental" }
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index 571cc46bc64..54457eacbf2 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -37,7 +37,7 @@ use rustc_privacy;
 use rustc_plugin::registry::Registry;
 use rustc_plugin as plugin;
 use rustc_passes::{self, ast_validation, loops, consts, hir_stats};
-use rustc_const_eval::{self, check_match};
+use rustc_mir::const_eval::check_match;
 use super::Compilation;
 
 use serialize::json;
@@ -942,7 +942,6 @@ pub fn default_provide(providers: &mut ty::maps::Providers) {
     ty::provide(providers);
     traits::provide(providers);
     reachable::provide(providers);
-    rustc_const_eval::provide(providers);
     rustc_passes::provide(providers);
     middle::region::provide(providers);
     cstore::provide(providers);
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 4b496fe3db6..4953b85f994 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -35,7 +35,6 @@ extern crate rustc;
 extern crate rustc_allocator;
 extern crate rustc_back;
 extern crate rustc_borrowck;
-extern crate rustc_const_eval;
 extern crate rustc_data_structures;
 extern crate rustc_errors as errors;
 extern crate rustc_passes;
@@ -1566,7 +1565,6 @@ pub fn diagnostics_registry() -> errors::registry::Registry {
     // FIXME: need to figure out a way to get these back in here
     // all_errors.extend_from_slice(get_trans(sess).diagnostics());
     all_errors.extend_from_slice(&rustc_trans_utils::DIAGNOSTICS);
-    all_errors.extend_from_slice(&rustc_const_eval::DIAGNOSTICS);
     all_errors.extend_from_slice(&rustc_metadata::DIAGNOSTICS);
     all_errors.extend_from_slice(&rustc_passes::DIAGNOSTICS);
     all_errors.extend_from_slice(&rustc_plugin::DIAGNOSTICS);
diff --git a/src/librustc_lint/Cargo.toml b/src/librustc_lint/Cargo.toml
index 9fee2d54e47..5ff891202db 100644
--- a/src/librustc_lint/Cargo.toml
+++ b/src/librustc_lint/Cargo.toml
@@ -12,6 +12,6 @@ test = false
 [dependencies]
 log = "0.4"
 rustc = { path = "../librustc" }
-rustc_const_eval = { path = "../librustc_const_eval" }
+rustc_mir = { path = "../librustc_mir"}
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index 9dc6d977851..79f3ff9f19f 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -39,7 +39,7 @@ extern crate syntax;
 extern crate rustc;
 #[macro_use]
 extern crate log;
-extern crate rustc_const_eval;
+extern crate rustc_mir;
 extern crate syntax_pos;
 
 use rustc::lint;
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index f400ce42a90..926aa2a7241 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -15,7 +15,7 @@ use rustc::ty::subst::Substs;
 use rustc::ty::{self, AdtKind, Ty, TyCtxt};
 use rustc::ty::layout::{self, LayoutOf};
 use middle::const_val::ConstVal;
-use rustc_const_eval::ConstContext;
+use rustc_mir::const_eval::ConstContext;
 use rustc::mir::interpret::{Value, PrimVal};
 use util::nodemap::FxHashSet;
 use lint::{LateContext, LintContext, LintArray};
diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml
index ea05a513f7e..90a0f18aba3 100644
--- a/src/librustc_mir/Cargo.toml
+++ b/src/librustc_mir/Cargo.toml
@@ -9,13 +9,13 @@ path = "lib.rs"
 crate-type = ["dylib"]
 
 [dependencies]
+arena = { path = "../libarena" }
 bitflags = "1.0"
 graphviz = { path = "../libgraphviz" }
 log = "0.4"
 log_settings = "0.1.1"
 rustc = { path = "../librustc" }
 rustc_back = { path = "../librustc_back" }
-rustc_const_eval = { path = "../librustc_const_eval" }
 rustc_const_math = { path = "../librustc_const_math" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index a325cfe3eaa..0f4d1e5bb0e 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -21,7 +21,7 @@ use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::subst::Substs;
 use rustc::util::nodemap::NodeMap;
 use rustc_back::PanicStrategy;
-use rustc_const_eval::pattern::{BindingMode, PatternKind};
+use const_eval::pattern::{BindingMode, PatternKind};
 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
 use shim;
 use std::mem;
diff --git a/src/librustc_const_eval/_match.rs b/src/librustc_mir/const_eval/_match.rs
index 9e9eb4a81d0..9ebbc111628 100644
--- a/src/librustc_const_eval/_match.rs
+++ b/src/librustc_mir/const_eval/_match.rs
@@ -13,15 +13,15 @@ use self::Usefulness::*;
 use self::WitnessPreference::*;
 
 use rustc::middle::const_val::ConstVal;
-use eval::{compare_const_vals};
+use const_eval::eval::{compare_const_vals};
 
 use rustc_const_math::ConstInt;
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::indexed_vec::Idx;
 
-use pattern::{FieldPattern, Pattern, PatternKind};
-use pattern::{PatternFoldable, PatternFolder};
+use const_eval::pattern::{FieldPattern, Pattern, PatternKind};
+use const_eval::pattern::{PatternFoldable, PatternFolder};
 
 use rustc::hir::def_id::DefId;
 use rustc::hir::RangeEnd;
diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_mir/const_eval/check_match.rs
index 6f7143c185c..3621d80df1d 100644
--- a/src/librustc_const_eval/check_match.rs
+++ b/src/librustc_mir/const_eval/check_match.rs
@@ -8,11 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use _match::{MatchCheckCtxt, Matrix, expand_pattern, is_useful};
-use _match::Usefulness::*;
-use _match::WitnessPreference::*;
+use const_eval::_match::{MatchCheckCtxt, Matrix, expand_pattern, is_useful};
+use const_eval::_match::Usefulness::*;
+use const_eval::_match::WitnessPreference::*;
 
-use pattern::{Pattern, PatternContext, PatternError, PatternKind};
+use const_eval::pattern::{Pattern, PatternContext, PatternError, PatternKind};
 
 use rustc::middle::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor};
 use rustc::middle::expr_use_visitor::{LoanCause, MutateMode};
diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_mir/const_eval/eval.rs
index 58fe40d12be..58fe40d12be 100644
--- a/src/librustc_const_eval/eval.rs
+++ b/src/librustc_mir/const_eval/eval.rs
diff --git a/src/librustc_mir/const_eval/mod.rs b/src/librustc_mir/const_eval/mod.rs
new file mode 100644
index 00000000000..27356c2b082
--- /dev/null
+++ b/src/librustc_mir/const_eval/mod.rs
@@ -0,0 +1,18 @@
+// Copyright 2016 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.
+
+//! constant evaluation on the HIR and code to validate patterns/matches
+
+mod eval;
+mod _match;
+pub mod check_match;
+pub mod pattern;
+
+pub use self::eval::*;
diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_mir/const_eval/pattern.rs
index a2daf22c3b4..a1109dbfdd1 100644
--- a/src/librustc_const_eval/pattern.rs
+++ b/src/librustc_mir/const_eval/pattern.rs
@@ -8,7 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use eval;
+use const_eval::eval;
+use interpret::{const_val_field, const_discr};
 
 use rustc::middle::const_val::{ConstEvalErr, ConstVal, ConstAggregate};
 use rustc::mir::{Field, BorrowKind, Mutability};
@@ -693,7 +694,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
             return match expr.node {
                 hir::ExprLit(ref lit) => {
                     let ty = self.tables.expr_ty(expr);
-                    match ::eval::lit_to_const(&lit.node, self.tcx, ty, false) {
+                    match super::eval::lit_to_const(&lit.node, self.tcx, ty, false) {
                         Ok(value) => PatternKind::Constant {
                             value: self.tcx.mk_const(ty::Const {
                                 ty,
@@ -716,7 +717,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
                         hir::ExprLit(ref lit) => lit,
                         _ => span_bug!(expr.span, "not a literal: {:?}", expr),
                     };
-                    match ::eval::lit_to_const(&lit.node, self.tcx, ty, true) {
+                    match super::eval::lit_to_const(&lit.node, self.tcx, ty, true) {
                         Ok(value) => PatternKind::Constant {
                             value: self.tcx.mk_const(ty::Const {
                                 ty,
@@ -782,9 +783,9 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
             ty::TyAdt(adt_def, substs) if adt_def.is_enum() => {
                 match cv.val {
                     ConstVal::Value(val) => {
-                        let discr = self.tcx.const_discr(self.param_env.and((
-                            instance, val, cv.ty
-                        ))).unwrap();
+                        let discr = const_discr(
+                            self.tcx, self.param_env, instance, val, cv.ty
+                        ).unwrap();
                         let variant_index = adt_def
                             .discriminants(self.tcx)
                             .position(|var| var.to_u128_unchecked() == discr)
@@ -801,8 +802,8 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
                                 .map(|(i, _)| {
                                 let field = Field::new(i);
                                 let val = match cv.val {
-                                    ConstVal::Value(miri) => self.tcx.const_val_field(
-                                        self.param_env.and((instance, field, miri, cv.ty)),
+                                    ConstVal::Value(miri) => const_val_field(
+                                        self.tcx, self.param_env, instance, field, miri, cv.ty,
                                     ).unwrap(),
                                     _ => bug!("{:#?} is not a valid tuple", cv),
                                 };
@@ -844,8 +845,8 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
                             ConstVal::Aggregate(ConstAggregate::Struct(consts)) => {
                                 consts.iter().find(|&&(name, _)| name == f.name).unwrap().1
                             },
-                            ConstVal::Value(miri) => self.tcx.const_val_field(
-                                self.param_env.and((instance, field, miri, cv.ty)),
+                            ConstVal::Value(miri) => const_val_field(
+                                self.tcx, self.param_env, instance, field, miri, cv.ty,
                             ).unwrap(),
                             _ => bug!("{:#?} is not a valid tuple", cv),
                         };
@@ -862,8 +863,8 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
                         let field = Field::new(i);
                         let val = match cv.val {
                             ConstVal::Aggregate(ConstAggregate::Tuple(consts)) => consts[i],
-                            ConstVal::Value(miri) => self.tcx.const_val_field(
-                                self.param_env.and((instance, field, miri, cv.ty)),
+                            ConstVal::Value(miri) => const_val_field(
+                                self.tcx, self.param_env, instance, field, miri, cv.ty,
                             ).unwrap(),
                             _ => bug!("{:#?} is not a valid tuple", cv),
                         };
@@ -882,8 +883,8 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
                         let val = match cv.val {
                             ConstVal::Aggregate(ConstAggregate::Array(consts)) => consts[i],
                             ConstVal::Aggregate(ConstAggregate::Repeat(cv, _)) => cv,
-                            ConstVal::Value(miri) => self.tcx.const_val_field(
-                                self.param_env.and((instance, field, miri, cv.ty)),
+                            ConstVal::Value(miri) => const_val_field(
+                                self.tcx, self.param_env, instance, field, miri, cv.ty,
                             ).unwrap(),
                             _ => bug!("{:#?} is not a valid tuple", cv),
                         };
diff --git a/src/librustc_mir/diagnostics.rs b/src/librustc_mir/diagnostics.rs
index 3491faf9cda..d71298fb1a6 100644
--- a/src/librustc_mir/diagnostics.rs
+++ b/src/librustc_mir/diagnostics.rs
@@ -12,6 +12,553 @@
 
 register_long_diagnostics! {
 
+
+E0001: r##"
+#### Note: this error code is no longer emitted by the compiler.
+
+This error suggests that the expression arm corresponding to the noted pattern
+will never be reached as for all possible values of the expression being
+matched, one of the preceding patterns will match.
+
+This means that perhaps some of the preceding patterns are too general, this
+one is too specific or the ordering is incorrect.
+
+For example, the following `match` block has too many arms:
+
+```
+match Some(0) {
+    Some(bar) => {/* ... */}
+    x => {/* ... */} // This handles the `None` case
+    _ => {/* ... */} // All possible cases have already been handled
+}
+```
+
+`match` blocks have their patterns matched in order, so, for example, putting
+a wildcard arm above a more specific arm will make the latter arm irrelevant.
+
+Ensure the ordering of the match arm is correct and remove any superfluous
+arms.
+"##,
+
+E0002: r##"
+#### Note: this error code is no longer emitted by the compiler.
+
+This error indicates that an empty match expression is invalid because the type
+it is matching on is non-empty (there exist values of this type). In safe code
+it is impossible to create an instance of an empty type, so empty match
+expressions are almost never desired. This error is typically fixed by adding
+one or more cases to the match expression.
+
+An example of an empty type is `enum Empty { }`. So, the following will work:
+
+```
+enum Empty {}
+
+fn foo(x: Empty) {
+    match x {
+        // empty
+    }
+}
+```
+
+However, this won't:
+
+```compile_fail
+fn foo(x: Option<String>) {
+    match x {
+        // empty
+    }
+}
+```
+"##,
+
+E0003: r##"
+#### Note: this error code is no longer emitted by the compiler.
+
+Not-a-Number (NaN) values cannot be compared for equality and hence can never
+match the input to a match expression. So, the following will not compile:
+
+```compile_fail
+const NAN: f32 = 0.0 / 0.0;
+
+let number = 0.1f32;
+
+match number {
+    NAN => { /* ... */ },
+    _ => {}
+}
+```
+
+To match against NaN values, you should instead use the `is_nan()` method in a
+guard, like so:
+
+```
+let number = 0.1f32;
+
+match number {
+    x if x.is_nan() => { /* ... */ }
+    _ => {}
+}
+```
+"##,
+
+E0004: r##"
+This error indicates that the compiler cannot guarantee a matching pattern for
+one or more possible inputs to a match expression. Guaranteed matches are
+required in order to assign values to match expressions, or alternatively,
+determine the flow of execution. Erroneous code example:
+
+```compile_fail,E0004
+enum Terminator {
+    HastaLaVistaBaby,
+    TalkToMyHand,
+}
+
+let x = Terminator::HastaLaVistaBaby;
+
+match x { // error: non-exhaustive patterns: `HastaLaVistaBaby` not covered
+    Terminator::TalkToMyHand => {}
+}
+```
+
+If you encounter this error you must alter your patterns so that every possible
+value of the input type is matched. For types with a small number of variants
+(like enums) you should probably cover all cases explicitly. Alternatively, the
+underscore `_` wildcard pattern can be added after all other patterns to match
+"anything else". Example:
+
+```
+enum Terminator {
+    HastaLaVistaBaby,
+    TalkToMyHand,
+}
+
+let x = Terminator::HastaLaVistaBaby;
+
+match x {
+    Terminator::TalkToMyHand => {}
+    Terminator::HastaLaVistaBaby => {}
+}
+
+// or:
+
+match x {
+    Terminator::TalkToMyHand => {}
+    _ => {}
+}
+```
+"##,
+
+E0005: r##"
+Patterns used to bind names must be irrefutable, that is, they must guarantee
+that a name will be extracted in all cases. Erroneous code example:
+
+```compile_fail,E0005
+let x = Some(1);
+let Some(y) = x;
+// error: refutable pattern in local binding: `None` not covered
+```
+
+If you encounter this error you probably need to use a `match` or `if let` to
+deal with the possibility of failure. Example:
+
+```
+let x = Some(1);
+
+match x {
+    Some(y) => {
+        // do something
+    },
+    None => {}
+}
+
+// or:
+
+if let Some(y) = x {
+    // do something
+}
+```
+"##,
+
+E0007: r##"
+This error indicates that the bindings in a match arm would require a value to
+be moved into more than one location, thus violating unique ownership. Code
+like the following is invalid as it requires the entire `Option<String>` to be
+moved into a variable called `op_string` while simultaneously requiring the
+inner `String` to be moved into a variable called `s`.
+
+```compile_fail,E0007
+let x = Some("s".to_string());
+
+match x {
+    op_string @ Some(s) => {}, // error: cannot bind by-move with sub-bindings
+    None => {},
+}
+```
+
+See also the error E0303.
+"##,
+
+E0008: r##"
+Names bound in match arms retain their type in pattern guards. As such, if a
+name is bound by move in a pattern, it should also be moved to wherever it is
+referenced in the pattern guard code. Doing so however would prevent the name
+from being available in the body of the match arm. Consider the following:
+
+```compile_fail,E0008
+match Some("hi".to_string()) {
+    Some(s) if s.len() == 0 => {}, // use s.
+    _ => {},
+}
+```
+
+The variable `s` has type `String`, and its use in the guard is as a variable of
+type `String`. The guard code effectively executes in a separate scope to the
+body of the arm, so the value would be moved into this anonymous scope and
+therefore becomes unavailable in the body of the arm.
+
+The problem above can be solved by using the `ref` keyword.
+
+```
+match Some("hi".to_string()) {
+    Some(ref s) if s.len() == 0 => {},
+    _ => {},
+}
+```
+
+Though this example seems innocuous and easy to solve, the problem becomes clear
+when it encounters functions which consume the value:
+
+```compile_fail,E0008
+struct A{}
+
+impl A {
+    fn consume(self) -> usize {
+        0
+    }
+}
+
+fn main() {
+    let a = Some(A{});
+    match a {
+        Some(y) if y.consume() > 0 => {}
+        _ => {}
+    }
+}
+```
+
+In this situation, even the `ref` keyword cannot solve it, since borrowed
+content cannot be moved. This problem cannot be solved generally. If the value
+can be cloned, here is a not-so-specific solution:
+
+```
+#[derive(Clone)]
+struct A{}
+
+impl A {
+    fn consume(self) -> usize {
+        0
+    }
+}
+
+fn main() {
+    let a = Some(A{});
+    match a{
+        Some(ref y) if y.clone().consume() > 0 => {}
+        _ => {}
+    }
+}
+```
+
+If the value will be consumed in the pattern guard, using its clone will not
+move its ownership, so the code works.
+"##,
+
+E0009: r##"
+In a pattern, all values that don't implement the `Copy` trait have to be bound
+the same way. The goal here is to avoid binding simultaneously by-move and
+by-ref.
+
+This limitation may be removed in a future version of Rust.
+
+Erroneous code example:
+
+```compile_fail,E0009
+struct X { x: (), }
+
+let x = Some((X { x: () }, X { x: () }));
+match x {
+    Some((y, ref z)) => {}, // error: cannot bind by-move and by-ref in the
+                            //        same pattern
+    None => panic!()
+}
+```
+
+You have two solutions:
+
+Solution #1: Bind the pattern's values the same way.
+
+```
+struct X { x: (), }
+
+let x = Some((X { x: () }, X { x: () }));
+match x {
+    Some((ref y, ref z)) => {},
+    // or Some((y, z)) => {}
+    None => panic!()
+}
+```
+
+Solution #2: Implement the `Copy` trait for the `X` structure.
+
+However, please keep in mind that the first solution should be preferred.
+
+```
+#[derive(Clone, Copy)]
+struct X { x: (), }
+
+let x = Some((X { x: () }, X { x: () }));
+match x {
+    Some((y, ref z)) => {},
+    None => panic!()
+}
+```
+"##,
+
+E0158: r##"
+`const` and `static` mean different things. A `const` is a compile-time
+constant, an alias for a literal value. This property means you can match it
+directly within a pattern.
+
+The `static` keyword, on the other hand, guarantees a fixed location in memory.
+This does not always mean that the value is constant. For example, a global
+mutex can be declared `static` as well.
+
+If you want to match against a `static`, consider using a guard instead:
+
+```
+static FORTY_TWO: i32 = 42;
+
+match Some(42) {
+    Some(x) if x == FORTY_TWO => {}
+    _ => {}
+}
+```
+"##,
+
+E0162: r##"
+An if-let pattern attempts to match the pattern, and enters the body if the
+match was successful. If the match is irrefutable (when it cannot fail to
+match), use a regular `let`-binding instead. For instance:
+
+```compile_fail,E0162
+struct Irrefutable(i32);
+let irr = Irrefutable(0);
+
+// This fails to compile because the match is irrefutable.
+if let Irrefutable(x) = irr {
+    // This body will always be executed.
+    // ...
+}
+```
+
+Try this instead:
+
+```
+struct Irrefutable(i32);
+let irr = Irrefutable(0);
+
+let Irrefutable(x) = irr;
+println!("{}", x);
+```
+"##,
+
+E0165: r##"
+A while-let pattern attempts to match the pattern, and enters the body if the
+match was successful. If the match is irrefutable (when it cannot fail to
+match), use a regular `let`-binding inside a `loop` instead. For instance:
+
+```compile_fail,E0165
+struct Irrefutable(i32);
+let irr = Irrefutable(0);
+
+// This fails to compile because the match is irrefutable.
+while let Irrefutable(x) = irr {
+    // ...
+}
+```
+
+Try this instead:
+
+```no_run
+struct Irrefutable(i32);
+let irr = Irrefutable(0);
+
+loop {
+    let Irrefutable(x) = irr;
+    // ...
+}
+```
+"##,
+
+E0170: r##"
+Enum variants are qualified by default. For example, given this type:
+
+```
+enum Method {
+    GET,
+    POST,
+}
+```
+
+You would match it using:
+
+```
+enum Method {
+    GET,
+    POST,
+}
+
+let m = Method::GET;
+
+match m {
+    Method::GET => {},
+    Method::POST => {},
+}
+```
+
+If you don't qualify the names, the code will bind new variables named "GET" and
+"POST" instead. This behavior is likely not what you want, so `rustc` warns when
+that happens.
+
+Qualified names are good practice, and most code works well with them. But if
+you prefer them unqualified, you can import the variants into scope:
+
+```
+use Method::*;
+enum Method { GET, POST }
+# fn main() {}
+```
+
+If you want others to be able to import variants from your module directly, use
+`pub use`:
+
+```
+pub use Method::*;
+pub enum Method { GET, POST }
+# fn main() {}
+```
+"##,
+
+
+E0297: r##"
+#### Note: this error code is no longer emitted by the compiler.
+
+Patterns used to bind names must be irrefutable. That is, they must guarantee
+that a name will be extracted in all cases. Instead of pattern matching the
+loop variable, consider using a `match` or `if let` inside the loop body. For
+instance:
+
+```compile_fail,E0005
+let xs : Vec<Option<i32>> = vec![Some(1), None];
+
+// This fails because `None` is not covered.
+for Some(x) in xs {
+    // ...
+}
+```
+
+Match inside the loop instead:
+
+```
+let xs : Vec<Option<i32>> = vec![Some(1), None];
+
+for item in xs {
+    match item {
+        Some(x) => {},
+        None => {},
+    }
+}
+```
+
+Or use `if let`:
+
+```
+let xs : Vec<Option<i32>> = vec![Some(1), None];
+
+for item in xs {
+    if let Some(x) = item {
+        // ...
+    }
+}
+```
+"##,
+
+E0301: r##"
+Mutable borrows are not allowed in pattern guards, because matching cannot have
+side effects. Side effects could alter the matched object or the environment
+on which the match depends in such a way, that the match would not be
+exhaustive. For instance, the following would not match any arm if mutable
+borrows were allowed:
+
+```compile_fail,E0301
+match Some(()) {
+    None => { },
+    option if option.take().is_none() => {
+        /* impossible, option is `Some` */
+    },
+    Some(_) => { } // When the previous match failed, the option became `None`.
+}
+```
+"##,
+
+E0302: r##"
+Assignments are not allowed in pattern guards, because matching cannot have
+side effects. Side effects could alter the matched object or the environment
+on which the match depends in such a way, that the match would not be
+exhaustive. For instance, the following would not match any arm if assignments
+were allowed:
+
+```compile_fail,E0302
+match Some(()) {
+    None => { },
+    option if { option = None; false } => { },
+    Some(_) => { } // When the previous match failed, the option became `None`.
+}
+```
+"##,
+
+E0303: r##"
+In certain cases it is possible for sub-bindings to violate memory safety.
+Updates to the borrow checker in a future version of Rust may remove this
+restriction, but for now patterns must be rewritten without sub-bindings.
+
+Before:
+
+```compile_fail,E0303
+match Some("hi".to_string()) {
+    ref op_string_ref @ Some(s) => {},
+    None => {},
+}
+```
+
+After:
+
+```
+match Some("hi".to_string()) {
+    Some(ref s) => {
+        let op_string_ref = &Some(s);
+        // ...
+    },
+    None => {},
+}
+```
+
+The `op_string_ref` binding has type `&Option<&String>` in both cases.
+
+See also https://github.com/rust-lang/rust/issues/14587
+"##,
+
 E0010: r##"
 The value of statics and constants must be known at compile time, and they live
 for the entire lifetime of a program. Creating a boxed value allocates memory on
@@ -1771,6 +2318,9 @@ b.resume();
 }
 
 register_diagnostics! {
+//  E0298, // cannot compare constants
+//  E0299, // mismatched types between arms
+//  E0471, // constant evaluation error (in pattern)
 //    E0385, // {} in an aliasable location
     E0493, // destructors cannot be evaluated at compile-time
     E0524, // two closures require unique access to `..` at the same time
diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs
index 09a31f9ab8f..329365c4415 100644
--- a/src/librustc_mir/hair/mod.rs
+++ b/src/librustc_mir/hair/mod.rs
@@ -27,7 +27,7 @@ use self::cx::Cx;
 
 pub mod cx;
 
-pub use rustc_const_eval::pattern::{BindingMode, Pattern, PatternKind, FieldPattern};
+pub use const_eval::pattern::{BindingMode, Pattern, PatternKind, FieldPattern};
 
 #[derive(Copy, Clone, Debug)]
 pub enum LintLevel {
diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs
index ec8215fb64c..f5408c73818 100644
--- a/src/librustc_mir/interpret/const_eval.rs
+++ b/src/librustc_mir/interpret/const_eval.rs
@@ -5,7 +5,7 @@ use rustc::hir::def_id::DefId;
 use rustc::mir;
 use rustc::middle::const_val::ErrKind::{CheckMatchError, TypeckError};
 use rustc::middle::const_val::{ConstEvalErr, ConstVal};
-use rustc_const_eval::{lookup_const_by_id, ConstContext};
+use const_eval::{lookup_const_by_id, ConstContext};
 use rustc::mir::Field;
 use rustc_data_structures::indexed_vec::Idx;
 
@@ -306,16 +306,19 @@ impl<'tcx> super::Machine<'tcx> for CompileTimeEvaluator {
 
 pub fn const_val_field<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    key: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, mir::Field, Value, Ty<'tcx>)>,
+    param_env: ty::ParamEnv<'tcx>,
+    instance: ty::Instance<'tcx>,
+    field: mir::Field,
+    val: Value,
+    ty: Ty<'tcx>,
 ) -> ::rustc::middle::const_val::EvalResult<'tcx> {
-    trace!("const_val_field: {:#?}", key);
-    match const_val_field_inner(tcx, key) {
+    match const_val_field_inner(tcx, param_env, instance, field, val, ty) {
         Ok((field, ty)) => Ok(tcx.mk_const(ty::Const {
             val: ConstVal::Value(field),
             ty,
         })),
         Err(err) => Err(ConstEvalErr {
-            span: tcx.def_span(key.value.0.def_id()),
+            span: tcx.def_span(instance.def_id()),
             kind: err.into(),
         }),
     }
@@ -323,11 +326,14 @@ pub fn const_val_field<'a, 'tcx>(
 
 fn const_val_field_inner<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    key: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, mir::Field, Value, Ty<'tcx>)>,
+    param_env: ty::ParamEnv<'tcx>,
+    instance: ty::Instance<'tcx>,
+    field: mir::Field,
+    value: Value,
+    ty: Ty<'tcx>,
 ) -> ::rustc::mir::interpret::EvalResult<'tcx, (Value, Ty<'tcx>)> {
-    trace!("const_val_field: {:#?}", key);
-    let (instance, field, value, ty) = key.value;
-    let mut ecx = mk_eval_cx(tcx, instance, key.param_env).unwrap();
+    trace!("const_val_field: {:?}, {:?}, {:?}, {:?}", instance, field, value, ty);
+    let mut ecx = mk_eval_cx(tcx, instance, param_env).unwrap();
     let (mut field, ty) = match value {
         Value::ByValPair(..) | Value::ByVal(_) => ecx.read_field(value, field, ty)?.expect("const_val_field on non-field"),
         Value::ByRef(ptr, align) => {
@@ -348,11 +354,13 @@ fn const_val_field_inner<'a, 'tcx>(
 
 pub fn const_discr<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    key: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, Value, Ty<'tcx>)>,
+    param_env: ty::ParamEnv<'tcx>,
+    instance: ty::Instance<'tcx>,
+    value: Value,
+    ty: Ty<'tcx>,
 ) -> EvalResult<'tcx, u128> {
-    trace!("const_discr: {:#?}", key);
-    let (instance, value, ty) = key.value;
-    let mut ecx = mk_eval_cx(tcx, instance, key.param_env).unwrap();
+    trace!("const_discr: {:?}, {:?}, {:?}", instance, value, ty);
+    let mut ecx = mk_eval_cx(tcx, instance, param_env).unwrap();
     let (ptr, align) = match value {
         Value::ByValPair(..) | Value::ByVal(_) => {
             let layout = ecx.layout_of(ty)?;
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index 8c15d1cf8b0..d25caa588fa 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -16,6 +16,8 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
 
 #![deny(warnings)]
 
+#![feature(slice_patterns)]
+#![feature(from_ref)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(catch_expr)]
@@ -38,6 +40,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
 #![feature(nonzero)]
 #![feature(underscore_lifetimes)]
 
+extern crate arena;
 #[macro_use]
 extern crate bitflags;
 #[macro_use] extern crate log;
@@ -52,7 +55,6 @@ extern crate syntax;
 extern crate syntax_pos;
 extern crate rustc_back;
 extern crate rustc_const_math;
-extern crate rustc_const_eval;
 extern crate core; // for NonZero
 extern crate log_settings;
 extern crate rustc_apfloat;
@@ -69,6 +71,7 @@ pub mod transform;
 pub mod util;
 pub mod interpret;
 pub mod monomorphize;
+pub mod const_eval;
 
 use rustc::ty::maps::Providers;
 
@@ -77,6 +80,7 @@ pub fn provide(providers: &mut Providers) {
     shim::provide(providers);
     transform::provide(providers);
     providers.const_eval = interpret::const_eval_provider;
+    providers.check_match = const_eval::check_match::check_match;
 }
 
 __build_diagnostic_array! { librustc_mir, DIAGNOSTICS }
diff --git a/src/librustc_passes/Cargo.toml b/src/librustc_passes/Cargo.toml
index e87e976eac3..4bab24ae139 100644
--- a/src/librustc_passes/Cargo.toml
+++ b/src/librustc_passes/Cargo.toml
@@ -11,7 +11,7 @@ crate-type = ["dylib"]
 [dependencies]
 log = "0.4"
 rustc = { path = "../librustc" }
-rustc_const_eval = { path = "../librustc_const_eval" }
+rustc_mir = { path = "../librustc_mir"}
 rustc_const_math = { path = "../librustc_const_math" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 syntax = { path = "../libsyntax" }
diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs
index 8153c3c8493..420e8c4aad2 100644
--- a/src/librustc_passes/consts.rs
+++ b/src/librustc_passes/consts.rs
@@ -25,7 +25,7 @@
 // by borrowck::gather_loans
 
 use rustc::ty::cast::CastKind;
-use rustc_const_eval::ConstContext;
+use rustc_mir::const_eval::ConstContext;
 use rustc::middle::const_val::ConstEvalErr;
 use rustc::middle::const_val::ErrKind::{IndexOpFeatureGated, UnimplementedConstVal, MiscCatchAll};
 use rustc::middle::const_val::ErrKind::{ErroneousReferencedConstant, MiscBinaryOp, NonConstPath};
diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs
index 8bd95982887..a51bee91499 100644
--- a/src/librustc_passes/lib.rs
+++ b/src/librustc_passes/lib.rs
@@ -23,7 +23,7 @@
 
 #[macro_use]
 extern crate rustc;
-extern crate rustc_const_eval;
+extern crate rustc_mir;
 extern crate rustc_const_math;
 extern crate rustc_data_structures;