Auto merge of #35168 - scottcarr:deaggregation, r=nikomatsakis

[MIR] Deaggregate structs to enable further optimizations

Currently, we generate MIR like:

```
tmp0 = ...;
tmp1 = ...;
tmp3 = Foo { a: ..., b: ... };
```

This PR implements "deaggregation," i.e.:

```
tmp3.0 = ...
tmp3.1 = ...
```

Currently, the code only deaggregates structs, not enums.  My understanding is that we do not have MIR to set the discriminant of an enum.
diff --git a/.travis.yml b/.travis.yml
index 87197a3..0abd858 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -7,6 +7,7 @@
 # our configure script, so disable auto submodule management.
 git:
   submodules: false
+  depth: 1
 
 before_install:
   - docker build -t rust -f src/etc/Dockerfile src/etc
diff --git a/configure b/configure
index d2ec457..29f16da 100755
--- a/configure
+++ b/configure
@@ -609,7 +609,7 @@
 opt inject-std-version 1 "inject the current compiler version of libstd into programs"
 opt llvm-version-check 1 "check if the LLVM version is supported, build anyway"
 opt rustbuild 0 "use the rust and cargo based build system"
-opt orbit 0 "get MIR where it belongs - everywhere; most importantly, in orbit"
+opt orbit 1 "get MIR where it belongs - everywhere; most importantly, in orbit"
 opt codegen-tests 1 "run the src/test/codegen tests"
 opt option-checking 1 "complain about unrecognized options in this configure script"
 opt ninja 0 "build LLVM using the Ninja generator (for MSVC, requires building in the correct environment)"
@@ -733,7 +733,7 @@
 if [ -n "$CFG_ENABLE_DEBUGINFO" ]; then putvar CFG_ENABLE_DEBUGINFO; fi
 if [ -n "$CFG_ENABLE_DEBUG_JEMALLOC" ]; then putvar CFG_ENABLE_DEBUG_JEMALLOC; fi
 
-if [ -n "$CFG_ENABLE_ORBIT" ]; then putvar CFG_ENABLE_ORBIT; fi
+if [ -n "$CFG_DISABLE_ORBIT" ]; then putvar CFG_DISABLE_ORBIT; fi
 
 step_msg "looking for build programs"
 
@@ -1020,6 +1020,12 @@
             err "bad LLVM version: $LLVM_VERSION, need >=3.7"
             ;;
     esac
+
+    if "$CFG_LLVM_ROOT/bin/llvm-mc" -help | grep -- "-relocation-model"; then
+        msg "found older llvm-mc"
+        CFG_LLVM_MC_HAS_RELOCATION_MODEL=1
+        putvar CFG_LLVM_MC_HAS_RELOCATION_MODEL
+    fi
 fi
 
 # Even when the user overrides the choice of CC, still try to detect
@@ -1192,7 +1198,7 @@
             ;;
 
 
-        x86_64-*-musl)
+        x86_64-*-musl | arm-*-musleabi)
             if [ ! -f $CFG_MUSL_ROOT/lib/libc.a ]
             then
                 err "musl libc $CFG_MUSL_ROOT/lib/libc.a not found"
diff --git a/mk/cfg/arm-unknown-linux-musleabi.mk b/mk/cfg/arm-unknown-linux-musleabi.mk
new file mode 100644
index 0000000..8120250
--- /dev/null
+++ b/mk/cfg/arm-unknown-linux-musleabi.mk
@@ -0,0 +1,3 @@
+# This file is intentially left empty to indicate that, while this target is
+# supported, it's not supported using plain GNU Make builds. Use a --rustbuild
+# instead.
\ No newline at end of file
diff --git a/mk/cfg/arm-unknown-linux-musleabihf.mk b/mk/cfg/arm-unknown-linux-musleabihf.mk
new file mode 100644
index 0000000..8120250
--- /dev/null
+++ b/mk/cfg/arm-unknown-linux-musleabihf.mk
@@ -0,0 +1,3 @@
+# This file is intentially left empty to indicate that, while this target is
+# supported, it's not supported using plain GNU Make builds. Use a --rustbuild
+# instead.
\ No newline at end of file
diff --git a/mk/cfg/armv7-unknown-linux-musleabihf.mk b/mk/cfg/armv7-unknown-linux-musleabihf.mk
new file mode 100644
index 0000000..8120250
--- /dev/null
+++ b/mk/cfg/armv7-unknown-linux-musleabihf.mk
@@ -0,0 +1,3 @@
+# This file is intentially left empty to indicate that, while this target is
+# supported, it's not supported using plain GNU Make builds. Use a --rustbuild
+# instead.
\ No newline at end of file
diff --git a/mk/cfg/x86_64-unknown-linux-musl.mk b/mk/cfg/x86_64-unknown-linux-musl.mk
index 3a03b2a..6f707ac 100644
--- a/mk/cfg/x86_64-unknown-linux-musl.mk
+++ b/mk/cfg/x86_64-unknown-linux-musl.mk
@@ -7,8 +7,8 @@
 CFG_LIB_NAME_x86_64-unknown-linux-musl=lib$(1).so
 CFG_STATIC_LIB_NAME_x86_64-unknown-linux-musl=lib$(1).a
 CFG_LIB_GLOB_x86_64-unknown-linux-musl=lib$(1)-*.so
-CFG_JEMALLOC_CFLAGS_x86_64-unknown-linux-musl := -m64
-CFG_GCCISH_CFLAGS_x86_64-unknown-linux-musl :=  -g -fPIC -m64
+CFG_JEMALLOC_CFLAGS_x86_64-unknown-linux-musl := -m64 -Wa,-mrelax-relocations=no
+CFG_GCCISH_CFLAGS_x86_64-unknown-linux-musl :=  -g -fPIC -m64 -Wa,-mrelax-relocations=no
 CFG_GCCISH_CXXFLAGS_x86_64-unknown-linux-musl :=
 CFG_GCCISH_LINK_FLAGS_x86_64-unknown-linux-musl :=
 CFG_GCCISH_DEF_FLAG_x86_64-unknown-linux-musl :=
diff --git a/mk/main.mk b/mk/main.mk
index fd12bf2..c6c3e70 100644
--- a/mk/main.mk
+++ b/mk/main.mk
@@ -162,9 +162,10 @@
   CFG_RUSTC_FLAGS += -g
 endif
 
-ifdef CFG_ENABLE_ORBIT
-  $(info cfg: launching MIR (CFG_ENABLE_ORBIT))
-  CFG_RUSTC_FLAGS += -Z orbit
+ifdef CFG_DISABLE_ORBIT
+  $(info cfg: HOLD HOLD HOLD (CFG_DISABLE_ORBIT))
+  RUSTFLAGS_STAGE1 += -Z orbit=off
+  RUSTFLAGS_STAGE2 += -Z orbit=off
 endif
 
 ifdef SAVE_TEMPS
diff --git a/mk/platform.mk b/mk/platform.mk
index c264462..d601cab 100644
--- a/mk/platform.mk
+++ b/mk/platform.mk
@@ -221,12 +221,19 @@
     LLVM_MC_RELOCATION_MODEL="default"
   endif
 
+  # LLVM changed this flag in 3.9
+  ifdef CFG_LLVM_MC_HAS_RELOCATION_MODEL
+    LLVM_MC_RELOC_FLAG := -relocation-model=$$(LLVM_MC_RELOCATION_MODEL)
+  else
+    LLVM_MC_RELOC_FLAG := -position-independent
+  endif
+
   # We're using llvm-mc as our assembler because it supports
   # .cfi pseudo-ops on mac
   CFG_ASSEMBLE_$(1)=$$(CPP_$(1)) -E $$(2) | \
                     $$(LLVM_MC_$$(CFG_BUILD)) \
                     -assemble \
-                    -relocation-model=$$(LLVM_MC_RELOCATION_MODEL) \
+                    $$(LLVM_MC_RELOC_FLAG) \
                     -filetype=obj \
                     -triple=$(1) \
                     -o=$$(1)
diff --git a/mk/rt.mk b/mk/rt.mk
index 067721f..e86aec6 100644
--- a/mk/rt.mk
+++ b/mk/rt.mk
@@ -384,7 +384,11 @@
 endif
 
 ifeq ($$(findstring msvc,$(1)),)
+
+ifeq ($$(findstring freebsd,$(1)),)
 COMPRT_OBJS_$(1) += gcc_personality_v0.o
+endif
+
 COMPRT_OBJS_$(1) += emutls.o
 
 ifeq ($$(findstring x86_64,$(1)),x86_64)
diff --git a/mk/rustllvm.mk b/mk/rustllvm.mk
index 834a11d..b50dbd0 100644
--- a/mk/rustllvm.mk
+++ b/mk/rustllvm.mk
@@ -24,7 +24,7 @@
 endif
 
 RUSTLLVM_OBJS_CS_$(1) := $$(addprefix rustllvm/, \
-	ExecutionEngineWrapper.cpp RustWrapper.cpp PassWrapper.cpp \
+	RustWrapper.cpp PassWrapper.cpp \
 	ArchiveWrapper.cpp)
 
 RUSTLLVM_INCS_$(1) = $$(LLVM_EXTRA_INCDIRS_$(1)) \
diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock
index 1290f2a..02698d6 100644
--- a/src/bootstrap/Cargo.lock
+++ b/src/bootstrap/Cargo.lock
@@ -7,8 +7,8 @@
  "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "gcc 0.3.31 (git+https://github.com/alexcrichton/gcc-rs)",
  "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "md5 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -33,7 +33,7 @@
 version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -53,7 +53,7 @@
 
 [[package]]
 name = "kernel32-sys"
-version = "0.2.1"
+version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -62,7 +62,7 @@
 
 [[package]]
 name = "libc"
-version = "0.2.9"
+version = "0.2.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -75,7 +75,7 @@
 version = "0.2.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 8ec9c7f..061192e 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -92,8 +92,7 @@
     }
     add_to_sysroot(&out_dir, &libdir);
 
-    if target.contains("musl") &&
-       (target.contains("x86_64") || target.contains("i686")) {
+    if target.contains("musl") && !target.contains("mips") {
         copy_third_party_objects(build, target, &libdir);
     }
 }
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index e64d7e5..aafbf68 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -72,6 +72,7 @@
     // libstd features
     pub debug_jemalloc: bool,
     pub use_jemalloc: bool,
+    pub backtrace: bool, // support for RUST_BACKTRACE
 
     // misc
     pub channel: String,
@@ -134,6 +135,7 @@
     debuginfo: Option<bool>,
     debug_jemalloc: Option<bool>,
     use_jemalloc: Option<bool>,
+    backtrace: Option<bool>,
     default_linker: Option<String>,
     default_ar: Option<String>,
     channel: Option<String>,
@@ -158,6 +160,7 @@
         let mut config = Config::default();
         config.llvm_optimize = true;
         config.use_jemalloc = true;
+        config.backtrace = true;
         config.rust_optimize = true;
         config.rust_optimize_tests = true;
         config.submodules = true;
@@ -230,6 +233,7 @@
             set(&mut config.rust_rpath, rust.rpath);
             set(&mut config.debug_jemalloc, rust.debug_jemalloc);
             set(&mut config.use_jemalloc, rust.use_jemalloc);
+            set(&mut config.backtrace, rust.backtrace);
             set(&mut config.channel, rust.channel.clone());
             config.rustc_default_linker = rust.default_linker.clone();
             config.rustc_default_ar = rust.default_ar.clone();
diff --git a/src/bootstrap/config.toml.example b/src/bootstrap/config.toml.example
index 6f06584..2894ada 100644
--- a/src/bootstrap/config.toml.example
+++ b/src/bootstrap/config.toml.example
@@ -99,6 +99,9 @@
 # Whether or not jemalloc is built with its debug option set
 #debug-jemalloc = false
 
+# Whether or not `panic!`s generate backtraces (RUST_BACKTRACE)
+#backtrace = true
+
 # The default linker that will be used by the generated compiler. Note that this
 # is not the linker used to link said compiler.
 #default-linker = "cc"
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 367322e8..acb7e0f 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -652,6 +652,9 @@
         if self.config.use_jemalloc {
             features.push_str(" jemalloc");
         }
+        if self.config.backtrace {
+            features.push_str(" backtrace");
+        }
         return features
     }
 
@@ -852,6 +855,12 @@
             base.push("-stdlib=libc++".into());
             base.push("-mmacosx-version-min=10.7".into());
         }
+        // This is a hack, because newer binutils broke things on some vms/distros
+        // (i.e., linking against unknown relocs disabled by the following flag)
+        // See: https://github.com/rust-lang/rust/issues/34978
+        if target == "x86_64-unknown-linux-musl" {
+            base.push("-Wa,-mrelax-relocations=no".into());
+        }
         return base
     }
 
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index 05ecbc0..a78cef4 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -348,7 +348,9 @@
             ]);
         }
     } else {
-        sources.push("gcc_personality_v0.c");
+        if !target.contains("freebsd") {
+            sources.push("gcc_personality_v0.c");
+        }
 
         if target.contains("x86_64") {
             sources.extend(vec![
diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs
index 7c0f09c..09f9678 100644
--- a/src/bootstrap/sanity.rs
+++ b/src/bootstrap/sanity.rs
@@ -31,6 +31,15 @@
 pub fn check(build: &mut Build) {
     let mut checked = HashSet::new();
     let path = env::var_os("PATH").unwrap_or(OsString::new());
+    // On Windows, quotes are invalid characters for filename paths, and if
+    // one is present as part of the PATH then that can lead to the system
+    // being unable to identify the files properly. See
+    // https://github.com/rust-lang/rust/issues/34959 for more details.
+    if cfg!(windows) {
+        if path.to_string_lossy().contains("\"") {
+            panic!("PATH contains invalid character '\"'");
+        }
+    }
     let mut need_cmd = |cmd: &OsStr| {
         if !checked.insert(cmd.to_owned()) {
             return
@@ -100,7 +109,7 @@
         }
 
         // Make sure musl-root is valid if specified
-        if target.contains("musl") && (target.contains("x86_64") || target.contains("i686")) {
+        if target.contains("musl") && !target.contains("mips") {
             match build.config.musl_root {
                 Some(ref root) => {
                     if fs::metadata(root.join("lib/libc.a")).is_err() {
diff --git a/src/compiler-rt b/src/compiler-rt
index ac3d1cd..8598065 160000
--- a/src/compiler-rt
+++ b/src/compiler-rt
@@ -1 +1 @@
-Subproject commit ac3d1cda612edccb6f1da53cbf7716e248405f3b
+Subproject commit 8598065bd965d9713bfafb6c1e766d63a7b17b89
diff --git a/src/doc/book/closures.md b/src/doc/book/closures.md
index 666d094..1470eac 100644
--- a/src/doc/book/closures.md
+++ b/src/doc/book/closures.md
@@ -223,6 +223,7 @@
 three separate traits to overload with:
 
 ```rust
+# #![feature(unboxed_closures)]
 # mod foo {
 pub trait Fn<Args> : FnMut<Args> {
     extern "rust-call" fn call(&self, args: Args) -> Self::Output;
@@ -291,9 +292,9 @@
 #   some_closure(1) }
 ```
 
-Because `Fn` is a trait, we can bound our generic with it. In this case, our
-closure takes a `i32` as an argument and returns an `i32`, and so the generic
-bound we use is `Fn(i32) -> i32`.
+Because `Fn` is a trait, we can use it as a bound for our generic type. In
+this case, our closure takes a `i32` as an argument and returns an `i32`, and
+so the generic bound we use is `Fn(i32) -> i32`.
 
 There’s one other key point here: because we’re bounding a generic with a
 trait, this will get monomorphized, and therefore, we’ll be doing static
diff --git a/src/doc/book/ffi.md b/src/doc/book/ffi.md
index 3cbe5d6..ca104ff 100644
--- a/src/doc/book/ffi.md
+++ b/src/doc/book/ffi.md
@@ -575,16 +575,69 @@
 
 # The "nullable pointer optimization"
 
-Certain types are defined to not be NULL. This includes references (`&T`,
-`&mut T`), boxes (`Box<T>`), and function pointers (`extern "abi" fn()`).
-When interfacing with C, pointers that might be NULL are often used.
-As a special case, a generic `enum` that contains exactly two variants, one of
-which contains no data and the other containing a single field, is eligible
-for the "nullable pointer optimization". When such an enum is instantiated
-with one of the non-nullable types, it is represented as a single pointer,
-and the non-data variant is represented as the NULL pointer. So
-`Option<extern "C" fn(c_int) -> c_int>` is how one represents a nullable
-function pointer using the C ABI.
+Certain Rust types are defined to never be `null`. This includes references (`&T`,
+`&mut T`), boxes (`Box<T>`), and function pointers (`extern "abi" fn()`). When
+interfacing with C, pointers that might be `null` are often used, which would seem to
+require some messy `transmute`s and/or unsafe code to handle conversions to/from Rust types.
+However, the language provides a workaround.
+
+As a special case, an `enum` is eligible for the "nullable pointer optimization" if it contains
+exactly two variants, one of which contains no data and the other contains a field of one of the
+non-nullable types listed above.  This means no extra space is required for a discriminant; rather,
+the empty variant is represented by putting a `null` value into the non-nullable field. This is
+called an "optimization", but unlike other optimizations it is guaranteed to apply to eligible
+types.
+
+The most common type that takes advantage of the nullable pointer optimization is `Option<T>`,
+where `None` corresponds to `null`. So `Option<extern "C" fn(c_int) -> c_int>` is a correct way
+to represent a nullable function pointer using the C ABI (corresponding to the C type
+`int (*)(int)`).
+
+Here is a contrived example. Let's say some C library has a facility for registering a
+callback, which gets called in certain situations. The callback is passed a function pointer
+and an integer and it is supposed to run the function with the integer as a parameter. So
+we have function pointers flying across the FFI boundary in both directions.
+
+```rust
+# #![feature(libc)]
+extern crate libc;
+use libc::c_int;
+
+# #[cfg(hidden)]
+extern "C" {
+    /// Register the callback.
+    fn register(cb: Option<extern "C" fn(Option<extern "C" fn(c_int) -> c_int>, c_int) -> c_int>);
+}
+# unsafe fn register(_: Option<extern "C" fn(Option<extern "C" fn(c_int) -> c_int>,
+#                                            c_int) -> c_int>)
+# {}
+
+/// This fairly useless function receives a function pointer and an integer
+/// from C, and returns the result of calling the function with the integer.
+/// In case no function is provided, it squares the integer by default.
+extern "C" fn apply(process: Option<extern "C" fn(c_int) -> c_int>, int: c_int) -> c_int {
+    match process {
+        Some(f) => f(int),
+        None    => int * int
+    }
+}
+
+fn main() {
+    unsafe {
+        register(Some(apply));
+    }
+}
+```
+
+And the code on the C side looks like this:
+
+```c
+void register(void (*f)(void (*)(int), int)) {
+    ...
+}
+```
+
+No `transmute` required!
 
 # Calling Rust code from C
 
diff --git a/src/doc/book/lang-items.md b/src/doc/book/lang-items.md
index b948567..72a3c08 100644
--- a/src/doc/book/lang-items.md
+++ b/src/doc/book/lang-items.md
@@ -15,7 +15,7 @@
 and one for deallocation. A freestanding program that uses the `Box`
 sugar for dynamic allocations via `malloc` and `free`:
 
-```rust
+```rust,ignore
 #![feature(lang_items, box_syntax, start, libc)]
 #![no_std]
 
diff --git a/src/etc/Dockerfile b/src/etc/Dockerfile
index 94be84a..83d5478 100644
--- a/src/etc/Dockerfile
+++ b/src/etc/Dockerfile
@@ -23,11 +23,5 @@
     libedit-dev zlib1g-dev \
     llvm-3.7-tools cmake
 
-# When we compile compiler-rt we pass it the llvm-config we just installed on
-# the system, but unfortunately it doesn't infer correctly where
-# LLVMConfig.cmake is so we need to coerce it a bit...
-RUN mkdir -p /usr/lib/llvm-3.7/build/share/llvm
-RUN ln -s /usr/share/llvm-3.7/cmake /usr/lib/llvm-3.7/build/share/llvm/cmake
-
 RUN mkdir /build
 WORKDIR /build
diff --git a/src/etc/char_private.py b/src/etc/char_private.py
new file mode 100644
index 0000000..3566d14
--- /dev/null
+++ b/src/etc/char_private.py
@@ -0,0 +1,154 @@
+#!/usr/bin/env python
+#
+# Copyright 2011-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.
+
+# This script uses the following Unicode tables:
+# - Categories.txt
+
+import os
+import subprocess
+
+def to_ranges(iter):
+    current = None
+    for i in iter:
+        if current is None or i != current[1] or i in (0x10000, 0x20000):
+            if current is not None:
+                yield tuple(current)
+            current = [i, i + 1]
+        else:
+            current[1] += 1
+    if current is not None:
+        yield tuple(current)
+
+def get_escaped(dictionary):
+    for i in range(0x110000):
+        if dictionary.get(i, "Cn") in "Cc Cf Cs Co Cn Zl Zp Zs".split() and i != ord(' '):
+            yield i
+
+def get_file(f):
+    try:
+        return open(os.path.basename(f))
+    except FileNotFoundError:
+        subprocess.run(["curl", "-O", f], check=True)
+        return open(os.path.basename(f))
+
+def main():
+    file = get_file("http://www.unicode.org/notes/tn36/Categories.txt")
+
+    dictionary = {int(line.split()[0], 16): line.split()[1] for line in file}
+
+    CUTOFF=0x10000
+    singletons0 = []
+    singletons1 = []
+    normal0 = []
+    normal1 = []
+    extra = []
+
+    for a, b in to_ranges(get_escaped(dictionary)):
+        if a > 2 * CUTOFF:
+            extra.append((a, b - a))
+        elif a == b - 1:
+            if a & CUTOFF:
+                singletons1.append(a & ~CUTOFF)
+            else:
+                singletons0.append(a)
+        elif a == b - 2:
+            if a & CUTOFF:
+                singletons1.append(a & ~CUTOFF)
+                singletons1.append((a + 1) & ~CUTOFF)
+            else:
+                singletons0.append(a)
+                singletons0.append(a + 1)
+        else:
+            if a >= 2 * CUTOFF:
+                extra.append((a, b - a))
+            elif a & CUTOFF:
+                normal1.append((a & ~CUTOFF, b - a))
+            else:
+                normal0.append((a, b - a))
+
+    print("""\
+// Copyright 2012-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.
+
+// NOTE: The following code was generated by "src/etc/char_private.py",
+//       do not edit directly!
+
+use slice::SliceExt;
+
+fn check(x: u16, singletons: &[u16], normal: &[u16]) -> bool {
+    for &s in singletons {
+        if x == s {
+            return false;
+        } else if x < s {
+            break;
+        }
+    }
+    for w in normal.chunks(2) {
+        let start = w[0];
+        let len = w[1];
+        let difference = (x as i32) - (start as i32);
+        if 0 <= difference {
+            if difference < len as i32 {
+                return false;
+            }
+        } else {
+            break;
+        }
+    }
+    true
+}
+
+pub fn is_printable(x: char) -> bool {
+    let x = x as u32;
+    let lower = x as u16;
+    if x < 0x10000 {
+        check(lower, SINGLETONS0, NORMAL0)
+    } else if x < 0x20000 {
+        check(lower, SINGLETONS1, NORMAL1)
+    } else {\
+""")
+    for a, b in extra:
+        print("        if 0x{:x} <= x && x < 0x{:x} {{".format(a, a + b))
+        print("            return false;")
+        print("        }")
+    print("""\
+        true
+    }
+}\
+""")
+    print()
+    print("const SINGLETONS0: &'static [u16] = &[")
+    for s in singletons0:
+        print("    0x{:x},".format(s))
+    print("];")
+    print("const SINGLETONS1: &'static [u16] = &[")
+    for s in singletons1:
+        print("    0x{:x},".format(s))
+    print("];")
+    print("const NORMAL0: &'static [u16] = &[")
+    for a, b in normal0:
+        print("    0x{:x}, 0x{:x},".format(a, b))
+    print("];")
+    print("const NORMAL1: &'static [u16] = &[")
+    for a, b in normal1:
+        print("    0x{:x}, 0x{:x},".format(a, b))
+    print("];")
+
+if __name__ == '__main__':
+    main()
diff --git a/src/etc/local_stage0.sh b/src/etc/local_stage0.sh
index 354be34..f5f39d2 100755
--- a/src/etc/local_stage0.sh
+++ b/src/etc/local_stage0.sh
@@ -58,6 +58,7 @@
 
 cp ${PREFIX}/bin/rustc${BIN_SUF} ${TARG_DIR}/stage0/bin/
 cp ${PREFIX}/${LIB_DIR}/${RUSTLIBDIR}/${TARG_DIR}/${LIB_DIR}/* ${TARG_DIR}/stage0/${LIB_DIR}/
+cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}arena*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/
 cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}extra*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/
 cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}rust*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/
 cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}std*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/
diff --git a/src/etc/mklldeps.py b/src/etc/mklldeps.py
index 8381e4f..24b0075 100644
--- a/src/etc/mklldeps.py
+++ b/src/etc/mklldeps.py
@@ -77,6 +77,13 @@
         lib = lib.strip()[2:]
     elif lib[0] == '-':
         lib = lib.strip()[1:]
+    # If this actually points at a literal file then we're on MSVC which now
+    # prints full paths, so get just the name of the library and strip off the
+    # trailing ".lib"
+    elif os.path.exists(lib):
+        lib = os.path.basename(lib)[:-4]
+    elif lib[-4:] == '.lib':
+        lib = lib[:-4]
     f.write("#[link(name = \"" + lib + "\"")
     if not llvm_shared and 'LLVM' in lib:
         f.write(", kind = \"static\"")
diff --git a/src/liballoc_jemalloc/Cargo.toml b/src/liballoc_jemalloc/Cargo.toml
index 768a0c2..25b3c8a 100644
--- a/src/liballoc_jemalloc/Cargo.toml
+++ b/src/liballoc_jemalloc/Cargo.toml
@@ -16,7 +16,7 @@
 
 [build-dependencies]
 build_helper = { path = "../build_helper" }
-gcc = "0.3.17"
+gcc = "0.3.27"
 
 [features]
 debug = []
diff --git a/src/liballoc_jemalloc/build.rs b/src/liballoc_jemalloc/build.rs
index d1b3583..dc1b8d6 100644
--- a/src/liballoc_jemalloc/build.rs
+++ b/src/liballoc_jemalloc/build.rs
@@ -73,7 +73,16 @@
                    .replace("\\", "/"))
        .current_dir(&build_dir)
        .env("CC", compiler.path())
-       .env("EXTRA_CFLAGS", cflags)
+       .env("EXTRA_CFLAGS", cflags.clone())
+       // jemalloc generates Makefile deps using GCC's "-MM" flag. This means
+       // that GCC will run the preprocessor, and only the preprocessor, over
+       // jemalloc's source files. If we don't specify CPPFLAGS, then at least
+       // on ARM that step fails with a "Missing implementation for 32-bit
+       // atomic operations" error. This is because no "-march" flag will be
+       // passed to GCC, and then GCC won't define the
+       // "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4" macro that jemalloc needs to
+       // select an atomic operation implementation.
+       .env("CPPFLAGS", cflags.clone())
        .env("AR", &ar)
        .env("RANLIB", format!("{} s", ar.display()));
 
diff --git a/src/libcollections/fmt.rs b/src/libcollections/fmt.rs
index c5312d0..be0ef85 100644
--- a/src/libcollections/fmt.rs
+++ b/src/libcollections/fmt.rs
@@ -434,37 +434,31 @@
 //!    in this case, if one uses the format string `{<arg>:<spec>.*}`, then the `<arg>` part refers
 //!    to the *value* to print, and the `precision` must come in the input preceding `<arg>`.
 //!
-//! For example, these:
+//! For example, the following calls all print the same thing `Hello x is 0.01000`:
 //!
 //! ```
-//! // Hello {arg 0 (x)} is {arg 1 (0.01) with precision specified inline (5)}
+//! // Hello {arg 0 ("x")} is {arg 1 (0.01) with precision specified inline (5)}
 //! println!("Hello {0} is {1:.5}", "x", 0.01);
 //!
-//! // Hello {arg 1 (x)} is {arg 2 (0.01) with precision specified in arg 0 (5)}
+//! // Hello {arg 1 ("x")} is {arg 2 (0.01) with precision specified in arg 0 (5)}
 //! println!("Hello {1} is {2:.0$}", 5, "x", 0.01);
 //!
-//! // Hello {arg 0 (x)} is {arg 2 (0.01) with precision specified in arg 1 (5)}
+//! // Hello {arg 0 ("x")} is {arg 2 (0.01) with precision specified in arg 1 (5)}
 //! println!("Hello {0} is {2:.1$}", "x", 5, 0.01);
 //!
-//! // Hello {next arg (x)} is {second of next two args (0.01) with precision
+//! // Hello {next arg ("x")} is {second of next two args (0.01) with precision
 //! //                          specified in first of next two args (5)}
 //! println!("Hello {} is {:.*}",    "x", 5, 0.01);
 //!
-//! // Hello {next arg (x)} is {arg 2 (0.01) with precision
+//! // Hello {next arg ("x")} is {arg 2 (0.01) with precision
 //! //                          specified in its predecessor (5)}
 //! println!("Hello {} is {2:.*}",   "x", 5, 0.01);
 //!
-//! // Hello {next arg (x)} is {arg "number" (0.01) with precision specified
+//! // Hello {next arg ("x")} is {arg "number" (0.01) with precision specified
 //! //                          in arg "prec" (5)}
 //! println!("Hello {} is {number:.prec$}", "x", prec = 5, number = 0.01);
 //! ```
 //!
-//! All print the same thing:
-//!
-//! ```text
-//! Hello x is 0.01000
-//! ```
-//!
 //! While these:
 //!
 //! ```
diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs
index f027d07..21387a1 100644
--- a/src/libcollections/lib.rs
+++ b/src/libcollections/lib.rs
@@ -33,6 +33,7 @@
 #![feature(allow_internal_unstable)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
+#![cfg_attr(not(test), feature(char_escape_debug))]
 #![feature(core_intrinsics)]
 #![feature(dropck_parametricity)]
 #![feature(fmt_internals)]
@@ -48,7 +49,6 @@
 #![feature(specialization)]
 #![feature(staged_api)]
 #![feature(step_by)]
-#![feature(unboxed_closures)]
 #![feature(unicode)]
 #![feature(unique)]
 #![feature(unsafe_no_drop_flag)]
diff --git a/src/libcollections/linked_list.rs b/src/libcollections/linked_list.rs
index 3d5c312..6842f02 100644
--- a/src/libcollections/linked_list.rs
+++ b/src/libcollections/linked_list.rs
@@ -203,19 +203,22 @@
     /// ```
     /// use std::collections::LinkedList;
     ///
-    /// let mut a = LinkedList::new();
-    /// let mut b = LinkedList::new();
-    /// a.push_back(1);
-    /// a.push_back(2);
-    /// b.push_back(3);
-    /// b.push_back(4);
+    /// let mut list1 = LinkedList::new();
+    /// list1.push_back('a');
     ///
-    /// a.append(&mut b);
+    /// let mut list2 = LinkedList::new();
+    /// list2.push_back('b');
+    /// list2.push_back('c');
     ///
-    /// for e in &a {
-    ///     println!("{}", e); // prints 1, then 2, then 3, then 4
-    /// }
-    /// println!("{}", b.len()); // prints 0
+    /// list1.append(&mut list2);
+    ///
+    /// let mut iter = list1.iter();
+    /// assert_eq!(iter.next(), Some(&'a'));
+    /// assert_eq!(iter.next(), Some(&'b'));
+    /// assert_eq!(iter.next(), Some(&'c'));
+    /// assert!(iter.next().is_none());
+    ///
+    /// assert!(list2.is_empty());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn append(&mut self, other: &mut Self) {
diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs
index ccef6c0..ff2b8cd 100644
--- a/src/libcollections/slice.rs
+++ b/src/libcollections/slice.rs
@@ -577,15 +577,13 @@
     ///
     /// # Example
     ///
-    /// Print the slice two elements at a time (i.e. `[1,2]`,
-    /// `[3,4]`, `[5]`):
-    ///
-    /// ```rust
-    /// let v = &[1, 2, 3, 4, 5];
-    ///
-    /// for chunk in v.chunks(2) {
-    ///     println!("{:?}", chunk);
-    /// }
+    /// ```
+    /// let slice = ['l', 'o', 'r', 'e', 'm'];
+    /// let mut iter = slice.chunks(2);
+    /// assert_eq!(iter.next().unwrap(), &['l', 'o']);
+    /// assert_eq!(iter.next().unwrap(), &['r', 'e']);
+    /// assert_eq!(iter.next().unwrap(), &['m']);
+    /// assert!(iter.next().is_none());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs
index 55308a4..4c64019 100644
--- a/src/libcollections/str.rs
+++ b/src/libcollections/str.rs
@@ -1697,6 +1697,14 @@
         return s;
     }
 
+    /// Escapes each char in `s` with `char::escape_debug`.
+    #[unstable(feature = "str_escape",
+               reason = "return type may change to be an iterator",
+               issue = "27791")]
+    pub fn escape_debug(&self) -> String {
+        self.chars().flat_map(|c| c.escape_debug()).collect()
+    }
+
     /// Escapes each char in `s` with `char::escape_default`.
     #[unstable(feature = "str_escape",
                reason = "return type may change to be an iterator",
diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs
index f91d8a5..0695225 100644
--- a/src/libcollections/string.rs
+++ b/src/libcollections/string.rs
@@ -1881,6 +1881,26 @@
     }
 }
 
+#[stable(feature = "stringfromchars", since = "1.12.0")]
+impl<'a> From<&'a [char]> for String {
+    #[inline]
+    fn from(v: &'a [char]) -> String {
+        let mut s = String::with_capacity(v.len());
+        for c in v {
+            s.push(*c);
+        }
+        s
+    }
+}
+
+#[stable(feature = "stringfromchars", since = "1.12.0")]
+impl From<Vec<char>> for String {
+    #[inline]
+    fn from(v: Vec<char>) -> String {
+        String::from(v.as_slice())
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Write for String {
     #[inline]
diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs
index 967bacc..275f38b 100644
--- a/src/libcollections/vec.rs
+++ b/src/libcollections/vec.rs
@@ -73,6 +73,7 @@
 use core::ops::{Index, IndexMut};
 use core::ops;
 use core::ptr;
+use core::ptr::Shared;
 use core::slice;
 
 use super::SpecExtend;
@@ -899,8 +900,8 @@
             Drain {
                 tail_start: end,
                 tail_len: len - end,
-                iter: range_slice.iter_mut(),
-                vec: self as *mut _,
+                iter: range_slice.iter(),
+                vec: Shared::new(self as *mut _),
             }
         }
     }
@@ -1806,8 +1807,8 @@
     /// Length of tail
     tail_len: usize,
     /// Current remaining range to remove
-    iter: slice::IterMut<'a, T>,
-    vec: *mut Vec<T>,
+    iter: slice::Iter<'a, T>,
+    vec: Shared<Vec<T>>,
 }
 
 #[stable(feature = "drain", since = "1.6.0")]
@@ -1845,7 +1846,7 @@
 
         if self.tail_len > 0 {
             unsafe {
-                let source_vec = &mut *self.vec;
+                let source_vec = &mut **self.vec;
                 // memmove back untouched tail, update to new length
                 let start = source_vec.len();
                 let tail = self.tail_start;
diff --git a/src/libcollectionstest/binary_heap.rs b/src/libcollectionstest/binary_heap.rs
index be933ab..e2a57bd 100644
--- a/src/libcollectionstest/binary_heap.rs
+++ b/src/libcollectionstest/binary_heap.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use std::collections::BinaryHeap;
+use std::collections::binary_heap::Drain;
 
 #[test]
 fn test_iterator() {
@@ -292,3 +293,8 @@
 
     assert_eq!(a.into_sorted_vec(), [-20, -10, 1, 2, 3, 3, 5, 43]);
 }
+
+#[allow(dead_code)]
+fn assert_covariance() {
+    fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> { d }
+}
diff --git a/src/libcollectionstest/str.rs b/src/libcollectionstest/str.rs
index 07428f3f..a61925c 100644
--- a/src/libcollectionstest/str.rs
+++ b/src/libcollectionstest/str.rs
@@ -704,15 +704,31 @@
 }
 
 #[test]
+fn test_escape_debug() {
+    assert_eq!("abc".escape_debug(), "abc");
+    assert_eq!("a c".escape_debug(), "a c");
+    assert_eq!("éèê".escape_debug(), "éèê");
+    assert_eq!("\r\n\t".escape_debug(), "\\r\\n\\t");
+    assert_eq!("'\"\\".escape_debug(), "\\'\\\"\\\\");
+    assert_eq!("\u{7f}\u{ff}".escape_debug(), "\\u{7f}\u{ff}");
+    assert_eq!("\u{100}\u{ffff}".escape_debug(), "\u{100}\\u{ffff}");
+    assert_eq!("\u{10000}\u{10ffff}".escape_debug(), "\u{10000}\\u{10ffff}");
+    assert_eq!("ab\u{200b}".escape_debug(), "ab\\u{200b}");
+    assert_eq!("\u{10d4ea}\r".escape_debug(), "\\u{10d4ea}\\r");
+}
+
+#[test]
 fn test_escape_default() {
     assert_eq!("abc".escape_default(), "abc");
     assert_eq!("a c".escape_default(), "a c");
+    assert_eq!("éèê".escape_default(), "\\u{e9}\\u{e8}\\u{ea}");
     assert_eq!("\r\n\t".escape_default(), "\\r\\n\\t");
     assert_eq!("'\"\\".escape_default(), "\\'\\\"\\\\");
+    assert_eq!("\u{7f}\u{ff}".escape_default(), "\\u{7f}\\u{ff}");
     assert_eq!("\u{100}\u{ffff}".escape_default(), "\\u{100}\\u{ffff}");
     assert_eq!("\u{10000}\u{10ffff}".escape_default(), "\\u{10000}\\u{10ffff}");
-    assert_eq!("ab\u{fb00}".escape_default(), "ab\\u{fb00}");
-    assert_eq!("\u{1d4ea}\r".escape_default(), "\\u{1d4ea}\\r");
+    assert_eq!("ab\u{200b}".escape_default(), "ab\\u{200b}");
+    assert_eq!("\u{10d4ea}\r".escape_default(), "\\u{10d4ea}\\r");
 }
 
 #[test]
diff --git a/src/libcollectionstest/string.rs b/src/libcollectionstest/string.rs
index 7f0fd28..1652fb5 100644
--- a/src/libcollectionstest/string.rs
+++ b/src/libcollectionstest/string.rs
@@ -193,6 +193,17 @@
 }
 
 #[test]
+fn test_add_assign() {
+    let mut s = String::new();
+    s += "";
+    assert_eq!(s.as_str(), "");
+    s += "abc";
+    assert_eq!(s.as_str(), "abc");
+    s += "ประเทศไทย中华Việt Nam";
+    assert_eq!(s.as_str(), "abcประเทศไทย中华Việt Nam");
+}
+
+#[test]
 fn test_push() {
     let mut data = String::from("ประเทศไทย中");
     data.push('华');
diff --git a/src/libcollectionstest/vec.rs b/src/libcollectionstest/vec.rs
index cb99659..7a6bd95 100644
--- a/src/libcollectionstest/vec.rs
+++ b/src/libcollectionstest/vec.rs
@@ -11,6 +11,7 @@
 use std::borrow::Cow;
 use std::iter::{FromIterator, repeat};
 use std::mem::size_of;
+use std::vec::Drain;
 
 use test::Bencher;
 
@@ -510,6 +511,11 @@
     }
 }
 
+#[allow(dead_code)]
+fn assert_covariance() {
+    fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> { d }
+}
+
 #[bench]
 fn bench_new(b: &mut Bencher) {
     b.iter(|| {
diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs
index 65cb1aa..06af200 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -847,6 +847,20 @@
 /// The `UnsafeCell<T>` type is the only legal way to obtain aliasable data that is considered
 /// mutable. In general, transmuting an `&T` type into an `&mut T` is considered undefined behavior.
 ///
+/// The compiler makes optimizations based on the knowledge that `&T` is not mutably aliased or
+/// mutated, and that `&mut T` is unique. When building abstractions like `Cell`, `RefCell`,
+/// `Mutex`, etc, you need to turn these optimizations off. `UnsafeCell` is the only legal way
+/// to do this. When `UnsafeCell<T>` is immutably aliased, it is still safe to obtain a mutable
+/// reference to its interior and/or to mutate it. However, it is up to the abstraction designer
+/// to ensure that no two mutable references obtained this way are active at the same time, and
+/// that there are no active mutable references or mutations when an immutable reference is obtained
+/// from the cell. This is often done via runtime checks.
+///
+/// Note that while mutating or mutably aliasing the contents of an `& UnsafeCell<T>` is
+/// okay (provided you enforce the invariants some other way); it is still undefined behavior
+/// to have multiple `&mut UnsafeCell<T>` aliases.
+///
+///
 /// Types like `Cell<T>` and `RefCell<T>` use this type to wrap their internal data.
 ///
 /// # Examples
@@ -916,6 +930,11 @@
 impl<T: ?Sized> UnsafeCell<T> {
     /// Gets a mutable pointer to the wrapped value.
     ///
+    /// This can be cast to a pointer of any kind.
+    /// Ensure that the access is unique when casting to
+    /// `&mut T`, and ensure that there are no mutations or mutable
+    /// aliases going on when casting to `&T`
+    ///
     /// # Examples
     ///
     /// ```
diff --git a/src/libcore/char.rs b/src/libcore/char.rs
index 0e7f04c..a3440fe 100644
--- a/src/libcore/char.rs
+++ b/src/libcore/char.rs
@@ -17,6 +17,7 @@
 
 use prelude::v1::*;
 
+use char_private::is_printable;
 use mem::transmute;
 
 // UTF-8 ranges and tags for encoding characters
@@ -263,6 +264,8 @@
     fn escape_unicode(self) -> EscapeUnicode;
     #[stable(feature = "core", since = "1.6.0")]
     fn escape_default(self) -> EscapeDefault;
+    #[unstable(feature = "char_escape_debug", issue = "35068")]
+    fn escape_debug(self) -> EscapeDebug;
     #[stable(feature = "core", since = "1.6.0")]
     fn len_utf8(self) -> usize;
     #[stable(feature = "core", since = "1.6.0")]
@@ -327,6 +330,19 @@
     }
 
     #[inline]
+    fn escape_debug(self) -> EscapeDebug {
+        let init_state = match self {
+            '\t' => EscapeDefaultState::Backslash('t'),
+            '\r' => EscapeDefaultState::Backslash('r'),
+            '\n' => EscapeDefaultState::Backslash('n'),
+            '\\' | '\'' | '"' => EscapeDefaultState::Backslash(self),
+            c if is_printable(c) => EscapeDefaultState::Char(c),
+            c => EscapeDefaultState::Unicode(c.escape_unicode()),
+        };
+        EscapeDebug(EscapeDefault { state: init_state })
+    }
+
+    #[inline]
     fn len_utf8(self) -> usize {
         let code = self as u32;
         if code < MAX_ONE_B {
@@ -600,6 +616,27 @@
     }
 }
 
+/// An iterator that yields the literal escape code of a `char`.
+///
+/// This `struct` is created by the [`escape_debug()`] method on [`char`]. See its
+/// documentation for more.
+///
+/// [`escape_debug()`]: ../../std/primitive.char.html#method.escape_debug
+/// [`char`]: ../../std/primitive.char.html
+#[unstable(feature = "char_escape_debug", issue = "35068")]
+#[derive(Clone, Debug)]
+pub struct EscapeDebug(EscapeDefault);
+
+#[unstable(feature = "char_escape_debug", issue = "35068")]
+impl Iterator for EscapeDebug {
+    type Item = char;
+    fn next(&mut self) -> Option<char> { self.0.next() }
+    fn size_hint(&self) -> (usize, Option<usize>) { self.0.size_hint() }
+}
+
+#[unstable(feature = "char_escape_debug", issue = "35068")]
+impl ExactSizeIterator for EscapeDebug { }
+
 /// An iterator over `u8` entries represending the UTF-8 encoding of a `char`
 /// value.
 ///
diff --git a/src/libcore/char_private.rs b/src/libcore/char_private.rs
new file mode 100644
index 0000000..1d8f95c
--- /dev/null
+++ b/src/libcore/char_private.rs
@@ -0,0 +1,695 @@
+// Copyright 2012-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.
+
+// NOTE: The following code was generated by "src/etc/char_private.py",
+//       do not edit directly!
+
+use slice::SliceExt;
+
+fn check(x: u16, singletons: &[u16], normal: &[u16]) -> bool {
+    for &s in singletons {
+        if x == s {
+            return false;
+        } else if x < s {
+            break;
+        }
+    }
+    for w in normal.chunks(2) {
+        let start = w[0];
+        let len = w[1];
+        let difference = (x as i32) - (start as i32);
+        if 0 <= difference {
+            if difference < len as i32 {
+                return false;
+            }
+        } else {
+            break;
+        }
+    }
+    true
+}
+
+pub fn is_printable(x: char) -> bool {
+    let x = x as u32;
+    let lower = x as u16;
+    if x < 0x10000 {
+        check(lower, SINGLETONS0, NORMAL0)
+    } else if x < 0x20000 {
+        check(lower, SINGLETONS1, NORMAL1)
+    } else {
+        if 0x20000 <= x && x < 0x2f800 {
+            return false;
+        }
+        if 0x2fa1e <= x && x < 0xe0100 {
+            return false;
+        }
+        if 0xe01f0 <= x && x < 0x110000 {
+            return false;
+        }
+        true
+    }
+}
+
+const SINGLETONS0: &'static [u16] = &[
+    0xad,
+    0x378,
+    0x379,
+    0x38b,
+    0x38d,
+    0x3a2,
+    0x557,
+    0x558,
+    0x560,
+    0x588,
+    0x590,
+    0x61c,
+    0x61d,
+    0x6dd,
+    0x70e,
+    0x70f,
+    0x74b,
+    0x74c,
+    0x82e,
+    0x82f,
+    0x83f,
+    0x85c,
+    0x85d,
+    0x8a1,
+    0x8ff,
+    0x978,
+    0x980,
+    0x984,
+    0x98d,
+    0x98e,
+    0x991,
+    0x992,
+    0x9a9,
+    0x9b1,
+    0x9ba,
+    0x9bb,
+    0x9c5,
+    0x9c6,
+    0x9c9,
+    0x9ca,
+    0x9de,
+    0x9e4,
+    0x9e5,
+    0xa04,
+    0xa11,
+    0xa12,
+    0xa29,
+    0xa31,
+    0xa34,
+    0xa37,
+    0xa3a,
+    0xa3b,
+    0xa3d,
+    0xa49,
+    0xa4a,
+    0xa5d,
+    0xa84,
+    0xa8e,
+    0xa92,
+    0xaa9,
+    0xab1,
+    0xab4,
+    0xaba,
+    0xabb,
+    0xac6,
+    0xaca,
+    0xace,
+    0xacf,
+    0xae4,
+    0xae5,
+    0xb04,
+    0xb0d,
+    0xb0e,
+    0xb11,
+    0xb12,
+    0xb29,
+    0xb31,
+    0xb34,
+    0xb3a,
+    0xb3b,
+    0xb45,
+    0xb46,
+    0xb49,
+    0xb4a,
+    0xb5e,
+    0xb64,
+    0xb65,
+    0xb84,
+    0xb91,
+    0xb9b,
+    0xb9d,
+    0xbc9,
+    0xbce,
+    0xbcf,
+    0xc04,
+    0xc0d,
+    0xc11,
+    0xc29,
+    0xc34,
+    0xc45,
+    0xc49,
+    0xc57,
+    0xc64,
+    0xc65,
+    0xc80,
+    0xc81,
+    0xc84,
+    0xc8d,
+    0xc91,
+    0xca9,
+    0xcb4,
+    0xcba,
+    0xcbb,
+    0xcc5,
+    0xcc9,
+    0xcdf,
+    0xce4,
+    0xce5,
+    0xcf0,
+    0xd04,
+    0xd0d,
+    0xd11,
+    0xd3b,
+    0xd3c,
+    0xd45,
+    0xd49,
+    0xd64,
+    0xd65,
+    0xd80,
+    0xd81,
+    0xd84,
+    0xdb2,
+    0xdbc,
+    0xdbe,
+    0xdbf,
+    0xdd5,
+    0xdd7,
+    0xe83,
+    0xe85,
+    0xe86,
+    0xe89,
+    0xe8b,
+    0xe8c,
+    0xe98,
+    0xea0,
+    0xea4,
+    0xea6,
+    0xea8,
+    0xea9,
+    0xeac,
+    0xeba,
+    0xebe,
+    0xebf,
+    0xec5,
+    0xec7,
+    0xece,
+    0xecf,
+    0xeda,
+    0xedb,
+    0xf48,
+    0xf98,
+    0xfbd,
+    0xfcd,
+    0x10c6,
+    0x10ce,
+    0x10cf,
+    0x1249,
+    0x124e,
+    0x124f,
+    0x1257,
+    0x1259,
+    0x125e,
+    0x125f,
+    0x1289,
+    0x128e,
+    0x128f,
+    0x12b1,
+    0x12b6,
+    0x12b7,
+    0x12bf,
+    0x12c1,
+    0x12c6,
+    0x12c7,
+    0x12d7,
+    0x1311,
+    0x1316,
+    0x1317,
+    0x135b,
+    0x135c,
+    0x1680,
+    0x170d,
+    0x176d,
+    0x1771,
+    0x17de,
+    0x17df,
+    0x180e,
+    0x180f,
+    0x196e,
+    0x196f,
+    0x1a1c,
+    0x1a1d,
+    0x1a5f,
+    0x1a7d,
+    0x1a7e,
+    0x1f16,
+    0x1f17,
+    0x1f1e,
+    0x1f1f,
+    0x1f46,
+    0x1f47,
+    0x1f4e,
+    0x1f4f,
+    0x1f58,
+    0x1f5a,
+    0x1f5c,
+    0x1f5e,
+    0x1f7e,
+    0x1f7f,
+    0x1fb5,
+    0x1fc5,
+    0x1fd4,
+    0x1fd5,
+    0x1fdc,
+    0x1ff0,
+    0x1ff1,
+    0x1ff5,
+    0x2072,
+    0x2073,
+    0x208f,
+    0x2700,
+    0x2c2f,
+    0x2c5f,
+    0x2d26,
+    0x2d2e,
+    0x2d2f,
+    0x2da7,
+    0x2daf,
+    0x2db7,
+    0x2dbf,
+    0x2dc7,
+    0x2dcf,
+    0x2dd7,
+    0x2ddf,
+    0x2e9a,
+    0x3040,
+    0x3097,
+    0x3098,
+    0x318f,
+    0x321f,
+    0x32ff,
+    0xa78f,
+    0xa9ce,
+    0xaa4e,
+    0xaa4f,
+    0xaa5a,
+    0xaa5b,
+    0xab07,
+    0xab08,
+    0xab0f,
+    0xab10,
+    0xab27,
+    0xabee,
+    0xabef,
+    0xfa6e,
+    0xfa6f,
+    0xfb37,
+    0xfb3d,
+    0xfb3f,
+    0xfb42,
+    0xfb45,
+    0xfd90,
+    0xfd91,
+    0xfdfe,
+    0xfdff,
+    0xfe53,
+    0xfe67,
+    0xfe75,
+    0xffc8,
+    0xffc9,
+    0xffd0,
+    0xffd1,
+    0xffd8,
+    0xffd9,
+    0xffe7,
+    0xfffe,
+    0xffff,
+];
+const SINGLETONS1: &'static [u16] = &[
+    0xc,
+    0x27,
+    0x3b,
+    0x3e,
+    0x4e,
+    0x4f,
+    0x31f,
+    0x39e,
+    0x49e,
+    0x49f,
+    0x806,
+    0x807,
+    0x809,
+    0x836,
+    0x83d,
+    0x83e,
+    0x856,
+    0xa04,
+    0xa14,
+    0xa18,
+    0xb56,
+    0xb57,
+    0x10bd,
+    0x1135,
+    0xd127,
+    0xd128,
+    0xd455,
+    0xd49d,
+    0xd4a0,
+    0xd4a1,
+    0xd4a3,
+    0xd4a4,
+    0xd4a7,
+    0xd4a8,
+    0xd4ad,
+    0xd4ba,
+    0xd4bc,
+    0xd4c4,
+    0xd506,
+    0xd50b,
+    0xd50c,
+    0xd515,
+    0xd51d,
+    0xd53a,
+    0xd53f,
+    0xd545,
+    0xd551,
+    0xd6a6,
+    0xd6a7,
+    0xd7cc,
+    0xd7cd,
+    0xee04,
+    0xee20,
+    0xee23,
+    0xee25,
+    0xee26,
+    0xee28,
+    0xee33,
+    0xee38,
+    0xee3a,
+    0xee48,
+    0xee4a,
+    0xee4c,
+    0xee50,
+    0xee53,
+    0xee55,
+    0xee56,
+    0xee58,
+    0xee5a,
+    0xee5c,
+    0xee5e,
+    0xee60,
+    0xee63,
+    0xee65,
+    0xee66,
+    0xee6b,
+    0xee73,
+    0xee78,
+    0xee7d,
+    0xee7f,
+    0xee8a,
+    0xeea4,
+    0xeeaa,
+    0xf0af,
+    0xf0b0,
+    0xf0bf,
+    0xf0c0,
+    0xf0d0,
+    0xf12f,
+    0xf336,
+    0xf3c5,
+    0xf43f,
+    0xf441,
+    0xf4f8,
+    0xf53e,
+    0xf53f,
+];
+const NORMAL0: &'static [u16] = &[
+    0x0, 0x20,
+    0x7f, 0x22,
+    0x37f, 0x5,
+    0x528, 0x9,
+    0x58b, 0x4,
+    0x5c8, 0x8,
+    0x5eb, 0x5,
+    0x5f5, 0x11,
+    0x7b2, 0xe,
+    0x7fb, 0x5,
+    0x85f, 0x41,
+    0x8ad, 0x37,
+    0x9b3, 0x3,
+    0x9cf, 0x8,
+    0x9d8, 0x4,
+    0x9fc, 0x5,
+    0xa0b, 0x4,
+    0xa43, 0x4,
+    0xa4e, 0x3,
+    0xa52, 0x7,
+    0xa5f, 0x7,
+    0xa76, 0xb,
+    0xad1, 0xf,
+    0xaf2, 0xf,
+    0xb4e, 0x8,
+    0xb58, 0x4,
+    0xb78, 0xa,
+    0xb8b, 0x3,
+    0xb96, 0x3,
+    0xba0, 0x3,
+    0xba5, 0x3,
+    0xbab, 0x3,
+    0xbba, 0x4,
+    0xbc3, 0x3,
+    0xbd1, 0x6,
+    0xbd8, 0xe,
+    0xbfb, 0x6,
+    0xc3a, 0x3,
+    0xc4e, 0x7,
+    0xc5a, 0x6,
+    0xc70, 0x8,
+    0xcce, 0x7,
+    0xcd7, 0x7,
+    0xcf3, 0xf,
+    0xd4f, 0x8,
+    0xd58, 0x8,
+    0xd76, 0x3,
+    0xd97, 0x3,
+    0xdc7, 0x3,
+    0xdcb, 0x4,
+    0xde0, 0x12,
+    0xdf5, 0xc,
+    0xe3b, 0x4,
+    0xe5c, 0x25,
+    0xe8e, 0x6,
+    0xee0, 0x20,
+    0xf6d, 0x4,
+    0xfdb, 0x25,
+    0x10c8, 0x5,
+    0x137d, 0x3,
+    0x139a, 0x6,
+    0x13f5, 0xb,
+    0x169d, 0x3,
+    0x16f1, 0xf,
+    0x1715, 0xb,
+    0x1737, 0x9,
+    0x1754, 0xc,
+    0x1774, 0xc,
+    0x17ea, 0x6,
+    0x17fa, 0x6,
+    0x181a, 0x6,
+    0x1878, 0x8,
+    0x18ab, 0x5,
+    0x18f6, 0xa,
+    0x191d, 0x3,
+    0x192c, 0x4,
+    0x193c, 0x4,
+    0x1941, 0x3,
+    0x1975, 0xb,
+    0x19ac, 0x4,
+    0x19ca, 0x6,
+    0x19db, 0x3,
+    0x1a8a, 0x6,
+    0x1a9a, 0x6,
+    0x1aae, 0x52,
+    0x1b4c, 0x4,
+    0x1b7d, 0x3,
+    0x1bf4, 0x8,
+    0x1c38, 0x3,
+    0x1c4a, 0x3,
+    0x1c80, 0x40,
+    0x1cc8, 0x8,
+    0x1cf7, 0x9,
+    0x1de7, 0x15,
+    0x1fff, 0x11,
+    0x2028, 0x8,
+    0x205f, 0x11,
+    0x209d, 0x3,
+    0x20ba, 0x16,
+    0x20f1, 0xf,
+    0x218a, 0x6,
+    0x23f4, 0xc,
+    0x2427, 0x19,
+    0x244b, 0x15,
+    0x2b4d, 0x3,
+    0x2b5a, 0xa6,
+    0x2cf4, 0x5,
+    0x2d28, 0x5,
+    0x2d68, 0x7,
+    0x2d71, 0xe,
+    0x2d97, 0x9,
+    0x2e3c, 0x44,
+    0x2ef4, 0xc,
+    0x2fd6, 0x1a,
+    0x2ffc, 0x5,
+    0x3100, 0x5,
+    0x312e, 0x3,
+    0x31bb, 0x5,
+    0x31e4, 0xc,
+    0x3400, 0x19c0,
+    0x4e00, 0x5200,
+    0xa48d, 0x3,
+    0xa4c7, 0x9,
+    0xa62c, 0x14,
+    0xa698, 0x7,
+    0xa6f8, 0x8,
+    0xa794, 0xc,
+    0xa7ab, 0x4d,
+    0xa82c, 0x4,
+    0xa83a, 0x6,
+    0xa878, 0x8,
+    0xa8c5, 0x9,
+    0xa8da, 0x6,
+    0xa8fc, 0x4,
+    0xa954, 0xb,
+    0xa97d, 0x3,
+    0xa9da, 0x4,
+    0xa9e0, 0x20,
+    0xaa37, 0x9,
+    0xaa7c, 0x4,
+    0xaac3, 0x18,
+    0xaaf7, 0xa,
+    0xab17, 0x9,
+    0xab2f, 0x91,
+    0xabfa, 0x2bb6,
+    0xd7c7, 0x4,
+    0xd7fc, 0x2104,
+    0xfada, 0x26,
+    0xfb07, 0xc,
+    0xfb18, 0x5,
+    0xfbc2, 0x11,
+    0xfd40, 0x10,
+    0xfdc8, 0x28,
+    0xfe1a, 0x6,
+    0xfe27, 0x9,
+    0xfe6c, 0x4,
+    0xfefd, 0x4,
+    0xffbf, 0x3,
+    0xffdd, 0x3,
+    0xffef, 0xd,
+];
+const NORMAL1: &'static [u16] = &[
+    0x5e, 0x22,
+    0xfb, 0x5,
+    0x103, 0x4,
+    0x134, 0x3,
+    0x18b, 0x5,
+    0x19c, 0x34,
+    0x1fe, 0x82,
+    0x29d, 0x3,
+    0x2d1, 0x2f,
+    0x324, 0xc,
+    0x34b, 0x35,
+    0x3c4, 0x4,
+    0x3d6, 0x2a,
+    0x4aa, 0x356,
+    0x839, 0x3,
+    0x860, 0xa0,
+    0x91c, 0x3,
+    0x93a, 0x5,
+    0x940, 0x40,
+    0x9b8, 0x6,
+    0x9c0, 0x40,
+    0xa07, 0x5,
+    0xa34, 0x4,
+    0xa3b, 0x4,
+    0xa48, 0x8,
+    0xa59, 0x7,
+    0xa80, 0x80,
+    0xb36, 0x3,
+    0xb73, 0x5,
+    0xb80, 0x80,
+    0xc49, 0x217,
+    0xe7f, 0x181,
+    0x104e, 0x4,
+    0x1070, 0x10,
+    0x10c2, 0xe,
+    0x10e9, 0x7,
+    0x10fa, 0x6,
+    0x1144, 0x3c,
+    0x11c9, 0x7,
+    0x11da, 0x4a6,
+    0x16b8, 0x8,
+    0x16ca, 0x936,
+    0x236f, 0x91,
+    0x2463, 0xd,
+    0x2474, 0xb8c,
+    0x342f, 0x33d1,
+    0x6a39, 0x4c7,
+    0x6f45, 0xb,
+    0x6f7f, 0x10,
+    0x6fa0, 0x4060,
+    0xb002, 0x1ffe,
+    0xd0f6, 0xa,
+    0xd173, 0x8,
+    0xd1de, 0x22,
+    0xd246, 0xba,
+    0xd357, 0x9,
+    0xd372, 0x8e,
+    0xd547, 0x3,
+    0xd800, 0x1600,
+    0xee3c, 0x6,
+    0xee43, 0x4,
+    0xee9c, 0x5,
+    0xeebc, 0x34,
+    0xeef2, 0x10e,
+    0xf02c, 0x4,
+    0xf094, 0xc,
+    0xf0e0, 0x20,
+    0xf10b, 0x5,
+    0xf16c, 0x4,
+    0xf19b, 0x4b,
+    0xf203, 0xd,
+    0xf23b, 0x5,
+    0xf249, 0x7,
+    0xf252, 0xae,
+    0xf321, 0xf,
+    0xf37d, 0x3,
+    0xf394, 0xc,
+    0xf3cb, 0x15,
+    0xf3f1, 0xf,
+    0xf4fd, 0x3,
+    0xf544, 0xc,
+    0xf568, 0x93,
+    0xf641, 0x4,
+    0xf650, 0x30,
+    0xf6c6, 0x3a,
+    0xf774, 0x88c,
+];
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index e5eb8f2..173c55e 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -1383,7 +1383,7 @@
         f.write_char('"')?;
         let mut from = 0;
         for (i, c) in self.char_indices() {
-            let esc = c.escape_default();
+            let esc = c.escape_debug();
             // If char needs escaping, flush backlog so far and write, else skip
             if esc.len() != 1 {
                 f.write_str(&self[from..i])?;
@@ -1409,7 +1409,7 @@
 impl Debug for char {
     fn fmt(&self, f: &mut Formatter) -> Result {
         f.write_char('\'')?;
-        for c in self.escape_default() {
+        for c in self.escape_debug() {
             f.write_char(c)?
         }
         f.write_char('\'')
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 0ad1f67..fabb390 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -103,17 +103,17 @@
 #[macro_use]
 mod uint_macros;
 
-#[path = "num/isize.rs"]  pub mod isize;
-#[path = "num/i8.rs"]   pub mod i8;
-#[path = "num/i16.rs"]  pub mod i16;
-#[path = "num/i32.rs"]  pub mod i32;
-#[path = "num/i64.rs"]  pub mod i64;
+#[path = "num/isize.rs"] pub mod isize;
+#[path = "num/i8.rs"]    pub mod i8;
+#[path = "num/i16.rs"]   pub mod i16;
+#[path = "num/i32.rs"]   pub mod i32;
+#[path = "num/i64.rs"]   pub mod i64;
 
 #[path = "num/usize.rs"] pub mod usize;
-#[path = "num/u8.rs"]   pub mod u8;
-#[path = "num/u16.rs"]  pub mod u16;
-#[path = "num/u32.rs"]  pub mod u32;
-#[path = "num/u64.rs"]  pub mod u64;
+#[path = "num/u8.rs"]    pub mod u8;
+#[path = "num/u16.rs"]   pub mod u16;
+#[path = "num/u32.rs"]   pub mod u32;
+#[path = "num/u64.rs"]   pub mod u64;
 
 #[path = "num/f32.rs"]   pub mod f32;
 #[path = "num/f64.rs"]   pub mod f64;
@@ -161,5 +161,6 @@
 pub mod fmt;
 
 // note: does not need to be public
+mod char_private;
 mod iter_private;
 mod tuple;
diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs
index 43868d1..b0c79a3 100644
--- a/src/libcore/macros.rs
+++ b/src/libcore/macros.rs
@@ -35,6 +35,17 @@
 /// This will invoke the `panic!` macro if the provided expression cannot be
 /// evaluated to `true` at runtime.
 ///
+/// Assertions are always checked in both debug and release builds, and cannot
+/// be disabled. See `debug_assert!` for assertions that are not enabled in
+/// release builds by default.
+///
+/// Unsafe code relies on `assert!` to enforce run-time invariants that, if
+/// violated could lead to unsafety.
+///
+/// Other use-cases of `assert!` include
+/// [testing](https://doc.rust-lang.org/book/testing.html) and enforcing
+/// run-time invariants in safe code (whose violation cannot result in unsafety).
+///
 /// This macro has a second version, where a custom panic message can be provided.
 ///
 /// # Examples
@@ -123,6 +134,13 @@
 /// expensive to be present in a release build but may be helpful during
 /// development.
 ///
+/// An unchecked assertion allows a program in an inconsistent state to keep
+/// running, which might have unexpected consequences but does not introduce
+/// unsafety as long as this only happens in safe code. The performance cost
+/// of assertions, is however, not measurable in general. Replacing `assert!`
+/// with `debug_assert!` is thus only encouraged after thorough profiling, and
+/// more importantly, only in safe code!
+///
 /// # Examples
 ///
 /// ```
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 97648cc..4636811 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -611,6 +611,31 @@
             if b {None} else {Some(a)}
         }
 
+        /// Checked absolute value. Computes `self.abs()`, returning `None` if
+        /// `self == MIN`.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        /// # #![feature(no_panic_abs)]
+        ///
+        /// use std::i32;
+        ///
+        /// assert_eq!((-5i32).checked_abs(), Some(5));
+        /// assert_eq!(i32::MIN.checked_abs(), None);
+        /// ```
+        #[unstable(feature = "no_panic_abs", issue = "35057")]
+        #[inline]
+        pub fn checked_abs(self) -> Option<Self> {
+            if self.is_negative() {
+                self.checked_neg()
+            } else {
+                Some(self)
+            }
+        }
+
         /// Saturating integer addition. Computes `self + other`, saturating at
         /// the numeric bounds instead of overflowing.
         ///
@@ -863,6 +888,36 @@
             self.overflowing_shr(rhs).0
         }
 
+        /// Wrapping (modular) absolute value. Computes `self.abs()`,
+        /// wrapping around at the boundary of the type.
+        ///
+        /// The only case where such wrapping can occur is when one takes
+        /// the absolute value of the negative minimal value for the type
+        /// this is a positive value that is too large to represent in the
+        /// type. In such a case, this function returns `MIN` itself.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        /// # #![feature(no_panic_abs)]
+        ///
+        /// assert_eq!(100i8.wrapping_abs(), 100);
+        /// assert_eq!((-100i8).wrapping_abs(), 100);
+        /// assert_eq!((-128i8).wrapping_abs(), -128);
+        /// assert_eq!((-128i8).wrapping_abs() as u8, 128);
+        /// ```
+        #[unstable(feature = "no_panic_abs", issue = "35057")]
+        #[inline(always)]
+        pub fn wrapping_abs(self) -> Self {
+            if self.is_negative() {
+                self.wrapping_neg()
+            } else {
+                self
+            }
+        }
+
         /// Calculates `self` + `rhs`
         ///
         /// Returns a tuple of the addition along with a boolean indicating
@@ -1071,6 +1126,35 @@
             (self >> (rhs & ($BITS - 1)), (rhs > ($BITS - 1)))
         }
 
+        /// Computes the absolute value of `self`.
+        ///
+        /// Returns a tuple of the absolute version of self along with a
+        /// boolean indicating whether an overflow happened. If self is the
+        /// minimum value (e.g. i32::MIN for values of type i32), then the
+        /// minimum value will be returned again and true will be returned for
+        /// an overflow happening.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        /// # #![feature(no_panic_abs)]
+        ///
+        /// assert_eq!(10i8.overflowing_abs(), (10,false));
+        /// assert_eq!((-10i8).overflowing_abs(), (10,false));
+        /// assert_eq!((-128i8).overflowing_abs(), (-128,true));
+        /// ```
+        #[unstable(feature = "no_panic_abs", issue = "35057")]
+        #[inline]
+        pub fn overflowing_abs(self) -> (Self, bool) {
+            if self.is_negative() {
+                self.overflowing_neg()
+            } else {
+                (self, false)
+            }
+        }
+
         /// Raises self to the power of `exp`, using exponentiation by squaring.
         ///
         /// # Examples
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index a32c9da..fdcadd4 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -459,6 +459,19 @@
     ///
     /// This has the same lifetime as the original slice, and so the
     /// iterator can continue to be used while this exists.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut chars = "abc".chars();
+    ///
+    /// assert_eq!(chars.as_str(), "abc");
+    /// chars.next();
+    /// assert_eq!(chars.as_str(), "bc");
+    /// chars.next();
+    /// chars.next();
+    /// assert_eq!(chars.as_str(), "");
+    /// ```
     #[stable(feature = "iter_to_slice", since = "1.4.0")]
     #[inline]
     pub fn as_str(&self) -> &'a str {
diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs
index 47d9deb..2a7a0b6 100644
--- a/src/libcore/sync/atomic.rs
+++ b/src/libcore/sync/atomic.rs
@@ -74,6 +74,8 @@
 //! ```
 
 #![stable(feature = "rust1", since = "1.0.0")]
+#![cfg_attr(not(target_has_atomic = "8"), allow(dead_code))]
+#![cfg_attr(not(target_has_atomic = "8"), allow(unused_imports))]
 
 use self::Ordering::*;
 
diff --git a/src/libcoretest/char.rs b/src/libcoretest/char.rs
index c8906fe..4632419 100644
--- a/src/libcoretest/char.rs
+++ b/src/libcoretest/char.rs
@@ -124,6 +124,49 @@
 }
 
 #[test]
+fn test_escape_debug() {
+    fn string(c: char) -> String {
+        c.escape_debug().collect()
+    }
+    let s = string('\n');
+    assert_eq!(s, "\\n");
+    let s = string('\r');
+    assert_eq!(s, "\\r");
+    let s = string('\'');
+    assert_eq!(s, "\\'");
+    let s = string('"');
+    assert_eq!(s, "\\\"");
+    let s = string(' ');
+    assert_eq!(s, " ");
+    let s = string('a');
+    assert_eq!(s, "a");
+    let s = string('~');
+    assert_eq!(s, "~");
+    let s = string('é');
+    assert_eq!(s, "é");
+    let s = string('\x00');
+    assert_eq!(s, "\\u{0}");
+    let s = string('\x1f');
+    assert_eq!(s, "\\u{1f}");
+    let s = string('\x7f');
+    assert_eq!(s, "\\u{7f}");
+    let s = string('\u{80}');
+    assert_eq!(s, "\\u{80}");
+    let s = string('\u{ff}');
+    assert_eq!(s, "\u{ff}");
+    let s = string('\u{11b}');
+    assert_eq!(s, "\u{11b}");
+    let s = string('\u{1d4b6}');
+    assert_eq!(s, "\u{1d4b6}");
+    let s = string('\u{200b}'); // zero width space
+    assert_eq!(s, "\\u{200b}");
+    let s = string('\u{e000}'); // private use 1
+    assert_eq!(s, "\\u{e000}");
+    let s = string('\u{100000}'); // private use 2
+    assert_eq!(s, "\\u{100000}");
+}
+
+#[test]
 fn test_escape_default() {
     fn string(c: char) -> String {
         c.escape_default().collect()
@@ -142,18 +185,28 @@
     assert_eq!(s, "a");
     let s = string('~');
     assert_eq!(s, "~");
+    let s = string('é');
+    assert_eq!(s, "\\u{e9}");
     let s = string('\x00');
     assert_eq!(s, "\\u{0}");
     let s = string('\x1f');
     assert_eq!(s, "\\u{1f}");
     let s = string('\x7f');
     assert_eq!(s, "\\u{7f}");
+    let s = string('\u{80}');
+    assert_eq!(s, "\\u{80}");
     let s = string('\u{ff}');
     assert_eq!(s, "\\u{ff}");
     let s = string('\u{11b}');
     assert_eq!(s, "\\u{11b}");
     let s = string('\u{1d4b6}');
     assert_eq!(s, "\\u{1d4b6}");
+    let s = string('\u{200b}'); // zero width space
+    assert_eq!(s, "\\u{200b}");
+    let s = string('\u{e000}'); // private use 1
+    assert_eq!(s, "\\u{e000}");
+    let s = string('\u{100000}'); // private use 2
+    assert_eq!(s, "\\u{100000}");
 }
 
 #[test]
diff --git a/src/libcoretest/lib.rs b/src/libcoretest/lib.rs
index 1ef2b58..9428b40 100644
--- a/src/libcoretest/lib.rs
+++ b/src/libcoretest/lib.rs
@@ -14,6 +14,7 @@
 #![feature(borrow_state)]
 #![feature(box_syntax)]
 #![feature(cell_extras)]
+#![feature(char_escape_debug)]
 #![feature(const_fn)]
 #![feature(core_private_bignum)]
 #![feature(core_private_diy_float)]
@@ -29,10 +30,9 @@
 #![feature(slice_patterns)]
 #![feature(step_by)]
 #![feature(test)]
-#![feature(unboxed_closures)]
+#![feature(try_from)]
 #![feature(unicode)]
 #![feature(unique)]
-#![feature(try_from)]
 
 extern crate core;
 extern crate test;
diff --git a/src/libflate/Cargo.toml b/src/libflate/Cargo.toml
index 52aa6bb..5423da9 100644
--- a/src/libflate/Cargo.toml
+++ b/src/libflate/Cargo.toml
@@ -11,4 +11,4 @@
 
 [build-dependencies]
 build_helper = { path = "../build_helper" }
-gcc = "0.3"
+gcc = "0.3.27"
diff --git a/src/liblibc b/src/liblibc
index b0d6253..5066b7d 160000
--- a/src/liblibc
+++ b/src/liblibc
@@ -1 +1 @@
-Subproject commit b0d62534d48b711c8978d1bbe8cca0558ae7b1cb
+Subproject commit 5066b7dcab7e700844b0e2ba71b8af9dc627a59b
diff --git a/src/libpanic_unwind/dwarf/eh.rs b/src/libpanic_unwind/dwarf/eh.rs
index 1e9e9e3..2284a9b 100644
--- a/src/libpanic_unwind/dwarf/eh.rs
+++ b/src/libpanic_unwind/dwarf/eh.rs
@@ -108,7 +108,7 @@
                 }
             }
         }
-        // Ip is not present in the table.  This should not hapen... but it does: issie #35011.
+        // Ip is not present in the table.  This should not happen... but it does: issue #35011.
         // So rather than returning EHAction::Terminate, we do this.
         EHAction::None
     } else {
diff --git a/src/libpanic_unwind/gcc.rs b/src/libpanic_unwind/gcc.rs
index cdf772a..fdae8f6 100644
--- a/src/libpanic_unwind/gcc.rs
+++ b/src/libpanic_unwind/gcc.rs
@@ -61,6 +61,8 @@
 use alloc::boxed::Box;
 
 use unwind as uw;
+use libc::{c_int, uintptr_t};
+use dwarf::eh::{self, EHContext, EHAction};
 
 #[repr(C)]
 struct Exception {
@@ -106,139 +108,184 @@
     0x4d4f5a_00_52555354
 }
 
-// All targets, except ARM which uses a slightly different ABI (however, iOS goes here as it uses
-// SjLj unwinding).  Also, 64-bit Windows implementation lives in seh64_gnu.rs
+
+// Register ids were lifted from LLVM's TargetLowering::getExceptionPointerRegister()
+// and TargetLowering::getExceptionSelectorRegister() for each architecture,
+// then mapped to DWARF register numbers via register definition tables
+// (typically <arch>RegisterInfo.td, search for "DwarfRegNum").
+// See also http://llvm.org/docs/WritingAnLLVMBackend.html#defining-a-register.
+
+#[cfg(target_arch = "x86")]
+const UNWIND_DATA_REG: (i32, i32) = (0, 2); // EAX, EDX
+
+#[cfg(target_arch = "x86_64")]
+const UNWIND_DATA_REG: (i32, i32) = (0, 1); // RAX, RDX
+
+#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
+const UNWIND_DATA_REG: (i32, i32) = (0, 1); // R0, R1 / X0, X1
+
+#[cfg(any(target_arch = "mips", target_arch = "mipsel"))]
+const UNWIND_DATA_REG: (i32, i32) = (4, 5); // A0, A1
+
+#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
+const UNWIND_DATA_REG: (i32, i32) = (3, 4); // R3, R4 / X3, X4
+
+// The following code is based on GCC's C and C++ personality routines.  For reference, see:
+// https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_personality.cc
+// https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c
+
+// The personality routine for most of our targets, except ARM, which has a slightly different ABI
+// (however, iOS goes here as it uses SjLj unwinding).  Also, the 64-bit Windows implementation
+// lives in seh64_gnu.rs
 #[cfg(all(any(target_os = "ios", not(target_arch = "arm"))))]
-pub mod eabi {
-    use unwind as uw;
-    use libc::{c_int, uintptr_t};
-    use dwarf::eh::{EHContext, EHAction, find_eh_action};
-
-    // Register ids were lifted from LLVM's TargetLowering::getExceptionPointerRegister()
-    // and TargetLowering::getExceptionSelectorRegister() for each architecture,
-    // then mapped to DWARF register numbers via register definition tables
-    // (typically <arch>RegisterInfo.td, search for "DwarfRegNum").
-    // See also http://llvm.org/docs/WritingAnLLVMBackend.html#defining-a-register.
-
-    #[cfg(target_arch = "x86")]
-    const UNWIND_DATA_REG: (i32, i32) = (0, 2); // EAX, EDX
-
-    #[cfg(target_arch = "x86_64")]
-    const UNWIND_DATA_REG: (i32, i32) = (0, 1); // RAX, RDX
-
-    #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
-    const UNWIND_DATA_REG: (i32, i32) = (0, 1); // R0, R1 / X0, X1
-
-    #[cfg(any(target_arch = "mips", target_arch = "mipsel"))]
-    const UNWIND_DATA_REG: (i32, i32) = (4, 5); // A0, A1
-
-    #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
-    const UNWIND_DATA_REG: (i32, i32) = (3, 4); // R3, R4 / X3, X4
-
-    // Based on GCC's C and C++ personality routines.  For reference, see:
-    // https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_personality.cc
-    // https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c
-    #[lang = "eh_personality"]
-    #[no_mangle]
-    #[allow(unused)]
-    unsafe extern "C" fn rust_eh_personality(version: c_int,
-                                             actions: uw::_Unwind_Action,
-                                             exception_class: uw::_Unwind_Exception_Class,
-                                             exception_object: *mut uw::_Unwind_Exception,
-                                             context: *mut uw::_Unwind_Context)
-                                             -> uw::_Unwind_Reason_Code {
-        if version != 1 {
-            return uw::_URC_FATAL_PHASE1_ERROR;
-        }
-        let lsda = uw::_Unwind_GetLanguageSpecificData(context) as *const u8;
-        let mut ip_before_instr: c_int = 0;
-        let ip = uw::_Unwind_GetIPInfo(context, &mut ip_before_instr);
-        let eh_context = EHContext {
-            // The return address points 1 byte past the call instruction,
-            // which could be in the next IP range in LSDA range table.
-            ip: if ip_before_instr != 0 { ip } else { ip - 1 },
-            func_start: uw::_Unwind_GetRegionStart(context),
-            get_text_start: &|| uw::_Unwind_GetTextRelBase(context),
-            get_data_start: &|| uw::_Unwind_GetDataRelBase(context),
-        };
-        let eh_action = find_eh_action(lsda, &eh_context);
-
-        if actions as i32 & uw::_UA_SEARCH_PHASE as i32 != 0 {
-            match eh_action {
-                EHAction::None | EHAction::Cleanup(_) => return uw::_URC_CONTINUE_UNWIND,
-                EHAction::Catch(_) => return uw::_URC_HANDLER_FOUND,
-                EHAction::Terminate => return uw::_URC_FATAL_PHASE1_ERROR,
-            }
-        } else {
-            match eh_action {
-                EHAction::None => return uw::_URC_CONTINUE_UNWIND,
-                EHAction::Cleanup(lpad) | EHAction::Catch(lpad) => {
-                    uw::_Unwind_SetGR(context, UNWIND_DATA_REG.0, exception_object as uintptr_t);
-                    uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, 0);
-                    uw::_Unwind_SetIP(context, lpad);
-                    return uw::_URC_INSTALL_CONTEXT;
-                }
-                EHAction::Terminate => return uw::_URC_FATAL_PHASE2_ERROR,
-            }
-        }
+#[lang = "eh_personality"]
+#[no_mangle]
+#[allow(unused)]
+unsafe extern "C" fn rust_eh_personality(version: c_int,
+                                         actions: uw::_Unwind_Action,
+                                         exception_class: uw::_Unwind_Exception_Class,
+                                         exception_object: *mut uw::_Unwind_Exception,
+                                         context: *mut uw::_Unwind_Context)
+                                         -> uw::_Unwind_Reason_Code {
+    if version != 1 {
+        return uw::_URC_FATAL_PHASE1_ERROR;
     }
-
-    #[cfg(stage0)]
-    #[lang = "eh_personality_catch"]
-    #[no_mangle]
-    pub unsafe extern "C" fn rust_eh_personality_catch(version: c_int,
-                                                       actions: uw::_Unwind_Action,
-                                                       exception_class: uw::_Unwind_Exception_Class,
-                                                       ue_header: *mut uw::_Unwind_Exception,
-                                                       context: *mut uw::_Unwind_Context)
-                                                       -> uw::_Unwind_Reason_Code {
-        rust_eh_personality(version, actions, exception_class, ue_header, context)
+    let eh_action = find_eh_action(context);
+    if actions as i32 & uw::_UA_SEARCH_PHASE as i32 != 0 {
+        match eh_action {
+            EHAction::None | EHAction::Cleanup(_) => return uw::_URC_CONTINUE_UNWIND,
+            EHAction::Catch(_) => return uw::_URC_HANDLER_FOUND,
+            EHAction::Terminate => return uw::_URC_FATAL_PHASE1_ERROR,
+        }
+    } else {
+        match eh_action {
+            EHAction::None => return uw::_URC_CONTINUE_UNWIND,
+            EHAction::Cleanup(lpad) | EHAction::Catch(lpad) => {
+                uw::_Unwind_SetGR(context, UNWIND_DATA_REG.0, exception_object as uintptr_t);
+                uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, 0);
+                uw::_Unwind_SetIP(context, lpad);
+                return uw::_URC_INSTALL_CONTEXT;
+            }
+            EHAction::Terminate => return uw::_URC_FATAL_PHASE2_ERROR,
+        }
     }
 }
 
-// ARM EHABI uses a slightly different personality routine signature,
-// but otherwise works the same.
+// ARM EHABI personality routine.
+// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf
 #[cfg(all(target_arch = "arm", not(target_os = "ios")))]
-pub mod eabi {
-    use unwind as uw;
-    use libc::c_int;
-
-    extern "C" {
-        fn __gcc_personality_v0(state: uw::_Unwind_State,
-                                ue_header: *mut uw::_Unwind_Exception,
-                                context: *mut uw::_Unwind_Context)
-                                -> uw::_Unwind_Reason_Code;
-    }
-
-    #[lang = "eh_personality"]
-    #[no_mangle]
-    extern "C" fn rust_eh_personality(state: uw::_Unwind_State,
-                                      ue_header: *mut uw::_Unwind_Exception,
-                                      context: *mut uw::_Unwind_Context)
-                                      -> uw::_Unwind_Reason_Code {
-        unsafe { __gcc_personality_v0(state, ue_header, context) }
-    }
-
-    #[lang = "eh_personality_catch"]
-    #[no_mangle]
-    pub extern "C" fn rust_eh_personality_catch(state: uw::_Unwind_State,
-                                                ue_header: *mut uw::_Unwind_Exception,
-                                                context: *mut uw::_Unwind_Context)
-                                                -> uw::_Unwind_Reason_Code {
+#[lang = "eh_personality"]
+#[no_mangle]
+unsafe extern "C" fn rust_eh_personality(state: uw::_Unwind_State,
+                                         exception_object: *mut uw::_Unwind_Exception,
+                                         context: *mut uw::_Unwind_Context)
+                                        -> uw::_Unwind_Reason_Code {
+    let state = state as c_int;
+    let action = state & uw::_US_ACTION_MASK as c_int;
+    let search_phase = if action == uw::_US_VIRTUAL_UNWIND_FRAME as c_int {
         // Backtraces on ARM will call the personality routine with
         // state == _US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND. In those cases
         // we want to continue unwinding the stack, otherwise all our backtraces
-        // would end at __rust_try.
-        if (state as c_int & uw::_US_ACTION_MASK as c_int) ==
-           uw::_US_VIRTUAL_UNWIND_FRAME as c_int &&
-           (state as c_int & uw::_US_FORCE_UNWIND as c_int) == 0 {
-            // search phase
-            uw::_URC_HANDLER_FOUND // catch!
-        } else {
-            // cleanup phase
-            unsafe { __gcc_personality_v0(state, ue_header, context) }
+        // would end at __rust_try
+        if state & uw::_US_FORCE_UNWIND as c_int != 0 {
+            return continue_unwind(exception_object, context)
+        }
+        true
+    } else if action == uw::_US_UNWIND_FRAME_STARTING as c_int {
+        false
+    } else if action == uw::_US_UNWIND_FRAME_RESUME as c_int {
+        return continue_unwind(exception_object, context);
+    } else {
+        return uw::_URC_FAILURE;
+    };
+
+    // The DWARF unwinder assumes that _Unwind_Context holds things like the function
+    // and LSDA pointers, however ARM EHABI places them into the exception object.
+    // To preserve signatures of functions like _Unwind_GetLanguageSpecificData(), which
+    // take only the context pointer, GCC personality routines stash a pointer to exception_object
+    // in the context, using location reserved for ARM's "scratch register" (r12).
+    uw::_Unwind_SetGR(context, uw::UNWIND_POINTER_REG, exception_object as uw::_Unwind_Ptr);
+    // ...A more principled approach would be to provide the full definition of ARM's
+    // _Unwind_Context in our libunwind bindings and fetch the required data from there directly,
+    // bypassing DWARF compatibility functions.
+
+    let eh_action = find_eh_action(context);
+    if search_phase {
+        match eh_action {
+            EHAction::None |
+            EHAction::Cleanup(_) => return continue_unwind(exception_object, context),
+            EHAction::Catch(_) => return uw::_URC_HANDLER_FOUND,
+            EHAction::Terminate => return uw::_URC_FAILURE,
+        }
+    } else {
+        match eh_action {
+            EHAction::None => return continue_unwind(exception_object, context),
+            EHAction::Cleanup(lpad) | EHAction::Catch(lpad) => {
+                uw::_Unwind_SetGR(context, UNWIND_DATA_REG.0, exception_object as uintptr_t);
+                uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, 0);
+                uw::_Unwind_SetIP(context, lpad);
+                return uw::_URC_INSTALL_CONTEXT;
+            }
+            EHAction::Terminate => return uw::_URC_FAILURE,
         }
     }
+
+    // On ARM EHABI the personality routine is responsible for actually
+    // unwinding a single stack frame before returning (ARM EHABI Sec. 6.1).
+    unsafe fn continue_unwind(exception_object: *mut uw::_Unwind_Exception,
+                              context: *mut uw::_Unwind_Context)
+                              -> uw::_Unwind_Reason_Code {
+        if __gnu_unwind_frame(exception_object, context) == uw::_URC_NO_REASON {
+            uw::_URC_CONTINUE_UNWIND
+        } else {
+            uw::_URC_FAILURE
+        }
+    }
+    // defined in libgcc
+    extern "C" {
+        fn __gnu_unwind_frame(exception_object: *mut uw::_Unwind_Exception,
+                                context: *mut uw::_Unwind_Context)
+                                -> uw::_Unwind_Reason_Code;
+    }
+}
+
+unsafe fn find_eh_action(context: *mut uw::_Unwind_Context) -> EHAction {
+    let lsda = uw::_Unwind_GetLanguageSpecificData(context) as *const u8;
+    let mut ip_before_instr: c_int = 0;
+    let ip = uw::_Unwind_GetIPInfo(context, &mut ip_before_instr);
+    let eh_context = EHContext {
+        // The return address points 1 byte past the call instruction,
+        // which could be in the next IP range in LSDA range table.
+        ip: if ip_before_instr != 0 { ip } else { ip - 1 },
+        func_start: uw::_Unwind_GetRegionStart(context),
+        get_text_start: &|| uw::_Unwind_GetTextRelBase(context),
+        get_data_start: &|| uw::_Unwind_GetDataRelBase(context),
+    };
+    eh::find_eh_action(lsda, &eh_context)
+}
+
+// *** Delete after a new snapshot ***
+#[cfg(all(stage0, any(target_os = "ios", not(target_arch = "arm"))))]
+#[lang = "eh_personality_catch"]
+#[no_mangle]
+pub unsafe extern "C" fn rust_eh_personality_catch(version: c_int,
+                                                    actions: uw::_Unwind_Action,
+                                                    exception_class: uw::_Unwind_Exception_Class,
+                                                    ue_header: *mut uw::_Unwind_Exception,
+                                                    context: *mut uw::_Unwind_Context)
+                                                    -> uw::_Unwind_Reason_Code {
+    rust_eh_personality(version, actions, exception_class, ue_header, context)
+}
+
+// *** Delete after a new snapshot ***
+#[cfg(all(stage0, target_arch = "arm", not(target_os = "ios")))]
+#[lang = "eh_personality_catch"]
+#[no_mangle]
+pub unsafe extern "C" fn rust_eh_personality_catch(state: uw::_Unwind_State,
+                                                    ue_header: *mut uw::_Unwind_Exception,
+                                                    context: *mut uw::_Unwind_Context)
+                                                    -> uw::_Unwind_Reason_Code {
+    rust_eh_personality(state, ue_header, context)
 }
 
 // See docs in the `unwind` module.
diff --git a/src/libpanic_unwind/seh64_gnu.rs b/src/libpanic_unwind/seh64_gnu.rs
index 7dc4288..3642e24 100644
--- a/src/libpanic_unwind/seh64_gnu.rs
+++ b/src/libpanic_unwind/seh64_gnu.rs
@@ -81,6 +81,7 @@
 // This is considered acceptable, because the behavior of throwing exceptions
 // through a C ABI boundary is undefined.
 
+// *** Delete after a new snapshot ***
 #[cfg(stage0)]
 #[lang = "eh_personality_catch"]
 #[cfg(not(test))]
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index 73b9665..c924753 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use std::fmt::Debug;
+use std::sync::Arc;
 
 macro_rules! try_opt {
     ($e:expr) => (
@@ -45,6 +46,10 @@
     // in an extern crate.
     MetaData(D),
 
+    // Represents some artifact that we save to disk. Note that these
+    // do not have a def-id as part of their identifier.
+    WorkProduct(Arc<WorkProductId>),
+
     // Represents different phases in the compiler.
     CrateReader,
     CollectLanguageItems,
@@ -189,6 +194,11 @@
             TransCrate => Some(TransCrate),
             TransWriteMetadata => Some(TransWriteMetadata),
             LinkBinary => Some(LinkBinary),
+
+            // work product names do not need to be mapped, because
+            // they are always absolute.
+            WorkProduct(ref id) => Some(WorkProduct(id.clone())),
+
             Hir(ref d) => op(d).map(Hir),
             MetaData(ref d) => op(d).map(MetaData),
             CollectItem(ref d) => op(d).map(CollectItem),
@@ -229,3 +239,12 @@
         }
     }
 }
+
+/// A "work product" corresponds to a `.o` (or other) file that we
+/// save in between runs. These ids do not have a DefId but rather
+/// some independent path or string that persists between runs without
+/// the need to be mapped or unmapped. (This ensures we can serialize
+/// them even in the absence of a tcx.)
+#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+pub struct WorkProductId(pub String);
+
diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs
index 741ad65..bb027b1 100644
--- a/src/librustc/dep_graph/graph.rs
+++ b/src/librustc/dep_graph/graph.rs
@@ -9,22 +9,45 @@
 // except according to those terms.
 
 use hir::def_id::DefId;
+use rustc_data_structures::fnv::FnvHashMap;
+use session::config::OutputType;
+use std::cell::{Ref, RefCell};
 use std::rc::Rc;
+use std::sync::Arc;
 
-use super::dep_node::DepNode;
+use super::dep_node::{DepNode, WorkProductId};
 use super::query::DepGraphQuery;
 use super::raii;
 use super::thread::{DepGraphThreadData, DepMessage};
 
 #[derive(Clone)]
 pub struct DepGraph {
-    data: Rc<DepGraphThreadData>
+    data: Rc<DepGraphData>
+}
+
+struct DepGraphData {
+    /// We send messages to the thread to let it build up the dep-graph
+    /// from the current run.
+    thread: DepGraphThreadData,
+
+    /// When we load, there may be `.o` files, cached mir, or other such
+    /// things available to us. If we find that they are not dirty, we
+    /// load the path to the file storing those work-products here into
+    /// this map. We can later look for and extract that data.
+    previous_work_products: RefCell<FnvHashMap<Arc<WorkProductId>, WorkProduct>>,
+
+    /// Work-products that we generate in this run.
+    work_products: RefCell<FnvHashMap<Arc<WorkProductId>, WorkProduct>>,
 }
 
 impl DepGraph {
     pub fn new(enabled: bool) -> DepGraph {
         DepGraph {
-            data: Rc::new(DepGraphThreadData::new(enabled))
+            data: Rc::new(DepGraphData {
+                thread: DepGraphThreadData::new(enabled),
+                previous_work_products: RefCell::new(FnvHashMap()),
+                work_products: RefCell::new(FnvHashMap())
+            })
         }
     }
 
@@ -32,19 +55,19 @@
     /// then the other methods on this `DepGraph` will have no net effect.
     #[inline]
     pub fn enabled(&self) -> bool {
-        self.data.enabled()
+        self.data.thread.enabled()
     }
 
     pub fn query(&self) -> DepGraphQuery<DefId> {
-        self.data.query()
+        self.data.thread.query()
     }
 
     pub fn in_ignore<'graph>(&'graph self) -> raii::IgnoreTask<'graph> {
-        raii::IgnoreTask::new(&self.data)
+        raii::IgnoreTask::new(&self.data.thread)
     }
 
     pub fn in_task<'graph>(&'graph self, key: DepNode<DefId>) -> raii::DepTask<'graph> {
-        raii::DepTask::new(&self.data, key)
+        raii::DepTask::new(&self.data.thread, key)
     }
 
     pub fn with_ignore<OP,R>(&self, op: OP) -> R
@@ -62,10 +85,84 @@
     }
 
     pub fn read(&self, v: DepNode<DefId>) {
-        self.data.enqueue(DepMessage::Read(v));
+        self.data.thread.enqueue(DepMessage::Read(v));
     }
 
     pub fn write(&self, v: DepNode<DefId>) {
-        self.data.enqueue(DepMessage::Write(v));
+        self.data.thread.enqueue(DepMessage::Write(v));
     }
+
+    /// Indicates that a previous work product exists for `v`. This is
+    /// invoked during initial start-up based on what nodes are clean
+    /// (and what files exist in the incr. directory).
+    pub fn insert_previous_work_product(&self, v: &Arc<WorkProductId>, data: WorkProduct) {
+        debug!("insert_previous_work_product({:?}, {:?})", v, data);
+        self.data.previous_work_products.borrow_mut()
+                                        .insert(v.clone(), data);
+    }
+
+    /// Indicates that we created the given work-product in this run
+    /// for `v`. This record will be preserved and loaded in the next
+    /// run.
+    pub fn insert_work_product(&self, v: &Arc<WorkProductId>, data: WorkProduct) {
+        debug!("insert_work_product({:?}, {:?})", v, data);
+        self.data.work_products.borrow_mut()
+                               .insert(v.clone(), data);
+    }
+
+    /// Check whether a previous work product exists for `v` and, if
+    /// so, return the path that leads to it. Used to skip doing work.
+    pub fn previous_work_product(&self, v: &Arc<WorkProductId>) -> Option<WorkProduct> {
+        self.data.previous_work_products.borrow()
+                                        .get(v)
+                                        .cloned()
+    }
+
+    /// Access the map of work-products created during this run. Only
+    /// used during saving of the dep-graph.
+    pub fn work_products(&self) -> Ref<FnvHashMap<Arc<WorkProductId>, WorkProduct>> {
+        self.data.work_products.borrow()
+    }
+}
+
+/// A "work product" is an intermediate result that we save into the
+/// incremental directory for later re-use. The primary example are
+/// the object files that we save for each partition at code
+/// generation time.
+///
+/// Each work product is associated with a dep-node, representing the
+/// process that produced the work-product. If that dep-node is found
+/// to be dirty when we load up, then we will delete the work-product
+/// at load time. If the work-product is found to be clean, then we
+/// will keep a record in the `previous_work_products` list.
+///
+/// In addition, work products have an associated hash. This hash is
+/// an extra hash that can be used to decide if the work-product from
+/// a previous compilation can be re-used (in addition to the dirty
+/// edges check).
+///
+/// As the primary example, consider the object files we generate for
+/// each partition. In the first run, we create partitions based on
+/// the symbols that need to be compiled. For each partition P, we
+/// hash the symbols in P and create a `WorkProduct` record associated
+/// with `DepNode::TransPartition(P)`; the hash is the set of symbols
+/// in P.
+///
+/// The next time we compile, if the `DepNode::TransPartition(P)` is
+/// judged to be clean (which means none of the things we read to
+/// generate the partition were found to be dirty), it will be loaded
+/// into previous work products. We will then regenerate the set of
+/// symbols in the partition P and hash them (note that new symbols
+/// may be added -- for example, new monomorphizations -- even if
+/// nothing in P changed!). We will compare that hash against the
+/// previous hash. If it matches up, we can reuse the object file.
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
+pub struct WorkProduct {
+    /// Extra hash used to decide if work-product is still suitable;
+    /// note that this is *not* a hash of the work-product itself.
+    /// See documentation on `WorkProduct` type for an example.
+    pub input_hash: u64,
+
+    /// Saved files associated with this CGU
+    pub saved_files: Vec<(OutputType, String)>,
 }
diff --git a/src/librustc/dep_graph/mod.rs b/src/librustc/dep_graph/mod.rs
index e65f6bb..a499cb1 100644
--- a/src/librustc/dep_graph/mod.rs
+++ b/src/librustc/dep_graph/mod.rs
@@ -20,7 +20,9 @@
 
 pub use self::dep_tracking_map::{DepTrackingMap, DepTrackingMapConfig};
 pub use self::dep_node::DepNode;
+pub use self::dep_node::WorkProductId;
 pub use self::graph::DepGraph;
+pub use self::graph::WorkProduct;
 pub use self::query::DepGraphQuery;
 pub use self::visit::visit_all_items_in_krate;
 pub use self::raii::DepTask;
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs
index 442c85a..aded220 100644
--- a/src/librustc/hir/intravisit.rs
+++ b/src/librustc/hir/intravisit.rs
@@ -94,11 +94,14 @@
 
     ///////////////////////////////////////////////////////////////////////////
 
+    fn visit_id(&mut self, _node_id: NodeId) {
+        // Nothing to do.
+    }
     fn visit_name(&mut self, _span: Span, _name: Name) {
         // Nothing to do.
     }
-    fn visit_mod(&mut self, m: &'v Mod, _s: Span, _n: NodeId) {
-        walk_mod(self, m)
+    fn visit_mod(&mut self, m: &'v Mod, _s: Span, n: NodeId) {
+        walk_mod(self, m, n)
     }
     fn visit_foreign_item(&mut self, i: &'v ForeignItem) {
         walk_foreign_item(self, i)
@@ -135,8 +138,8 @@
     fn visit_where_predicate(&mut self, predicate: &'v WherePredicate) {
         walk_where_predicate(self, predicate)
     }
-    fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: &'v Block, s: Span, _: NodeId) {
-        walk_fn(self, fk, fd, b, s)
+    fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: &'v Block, s: Span, id: NodeId) {
+        walk_fn(self, fk, fd, b, s, id)
     }
     fn visit_trait_item(&mut self, ti: &'v TraitItem) {
         walk_trait_item(self, ti)
@@ -157,7 +160,7 @@
                           s: &'v VariantData,
                           _: Name,
                           _: &'v Generics,
-                          _: NodeId,
+                          _parent_id: NodeId,
                           _: Span) {
         walk_struct_def(self, s)
     }
@@ -225,24 +228,28 @@
 }
 
 pub fn walk_macro_def<'v, V: Visitor<'v>>(visitor: &mut V, macro_def: &'v MacroDef) {
+    visitor.visit_id(macro_def.id);
     visitor.visit_name(macro_def.span, macro_def.name);
     walk_opt_name(visitor, macro_def.span, macro_def.imported_from);
     walk_list!(visitor, visit_attribute, &macro_def.attrs);
 }
 
-pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod) {
+pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod, mod_node_id: NodeId) {
+    visitor.visit_id(mod_node_id);
     for &item_id in &module.item_ids {
         visitor.visit_nested_item(item_id);
     }
 }
 
 pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) {
+    visitor.visit_id(local.id);
     visitor.visit_pat(&local.pat);
     walk_list!(visitor, visit_ty, &local.ty);
     walk_list!(visitor, visit_expr, &local.init);
 }
 
 pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) {
+    visitor.visit_id(lifetime.id);
     visitor.visit_name(lifetime.span, lifetime.name);
 }
 
@@ -263,6 +270,7 @@
 pub fn walk_trait_ref<'v, V>(visitor: &mut V, trait_ref: &'v TraitRef)
     where V: Visitor<'v>
 {
+    visitor.visit_id(trait_ref.ref_id);
     visitor.visit_path(&trait_ref.path, trait_ref.ref_id)
 }
 
@@ -271,9 +279,11 @@
     visitor.visit_name(item.span, item.name);
     match item.node {
         ItemExternCrate(opt_name) => {
+            visitor.visit_id(item.id);
             walk_opt_name(visitor, item.span, opt_name)
         }
         ItemUse(ref vp) => {
+            visitor.visit_id(item.id);
             match vp.node {
                 ViewPathSimple(name, ref path) => {
                     visitor.visit_name(vp.span, name);
@@ -292,6 +302,7 @@
         }
         ItemStatic(ref typ, _, ref expr) |
         ItemConst(ref typ, ref expr) => {
+            visitor.visit_id(item.id);
             visitor.visit_ty(typ);
             visitor.visit_expr(expr);
         }
@@ -309,23 +320,29 @@
                              item.id)
         }
         ItemMod(ref module) => {
+            // visit_mod() takes care of visiting the Item's NodeId
             visitor.visit_mod(module, item.span, item.id)
         }
         ItemForeignMod(ref foreign_module) => {
+            visitor.visit_id(item.id);
             walk_list!(visitor, visit_foreign_item, &foreign_module.items);
         }
         ItemTy(ref typ, ref type_parameters) => {
+            visitor.visit_id(item.id);
             visitor.visit_ty(typ);
             visitor.visit_generics(type_parameters)
         }
         ItemEnum(ref enum_definition, ref type_parameters) => {
             visitor.visit_generics(type_parameters);
+            // visit_enum_def() takes care of visiting the Item's NodeId
             visitor.visit_enum_def(enum_definition, type_parameters, item.id, item.span)
         }
         ItemDefaultImpl(_, ref trait_ref) => {
+            visitor.visit_id(item.id);
             visitor.visit_trait_ref(trait_ref)
         }
         ItemImpl(_, _, ref type_parameters, ref opt_trait_reference, ref typ, ref impl_items) => {
+            visitor.visit_id(item.id);
             visitor.visit_generics(type_parameters);
             walk_list!(visitor, visit_trait_ref, opt_trait_reference);
             visitor.visit_ty(typ);
@@ -333,9 +350,11 @@
         }
         ItemStruct(ref struct_definition, ref generics) => {
             visitor.visit_generics(generics);
+            visitor.visit_id(item.id);
             visitor.visit_variant_data(struct_definition, item.name, generics, item.id, item.span);
         }
         ItemTrait(_, ref generics, ref bounds, ref methods) => {
+            visitor.visit_id(item.id);
             visitor.visit_generics(generics);
             walk_list!(visitor, visit_ty_param_bound, bounds);
             walk_list!(visitor, visit_trait_item, methods);
@@ -348,6 +367,7 @@
                                          enum_definition: &'v EnumDef,
                                          generics: &'v Generics,
                                          item_id: NodeId) {
+    visitor.visit_id(item_id);
     walk_list!(visitor,
                visit_variant,
                &enum_definition.variants,
@@ -358,18 +378,20 @@
 pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V,
                                         variant: &'v Variant,
                                         generics: &'v Generics,
-                                        item_id: NodeId) {
+                                        parent_item_id: NodeId) {
     visitor.visit_name(variant.span, variant.node.name);
     visitor.visit_variant_data(&variant.node.data,
                                variant.node.name,
                                generics,
-                               item_id,
+                               parent_item_id,
                                variant.span);
     walk_list!(visitor, visit_expr, &variant.node.disr_expr);
     walk_list!(visitor, visit_attribute, &variant.node.attrs);
 }
 
 pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
+    visitor.visit_id(typ.id);
+
     match typ.node {
         TyVec(ref ty) => {
             visitor.visit_ty(ty)
@@ -421,6 +443,7 @@
 pub fn walk_path_list_item<'v, V: Visitor<'v>>(visitor: &mut V,
                                                _prefix: &'v Path,
                                                item: &'v PathListItem) {
+    visitor.visit_id(item.node.id());
     walk_opt_name(visitor, item.span, item.node.name());
     walk_opt_name(visitor, item.span, item.node.rename());
 }
@@ -450,11 +473,13 @@
 
 pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(visitor: &mut V,
                                                    type_binding: &'v TypeBinding) {
+    visitor.visit_id(type_binding.id);
     visitor.visit_name(type_binding.span, type_binding.name);
     visitor.visit_ty(&type_binding.ty);
 }
 
 pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
+    visitor.visit_id(pattern.id);
     match pattern.node {
         PatKind::TupleStruct(ref path, ref children, _) => {
             visitor.visit_path(path, pattern.id);
@@ -499,6 +524,7 @@
 }
 
 pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v ForeignItem) {
+    visitor.visit_id(foreign_item.id);
     visitor.visit_vis(&foreign_item.vis);
     visitor.visit_name(foreign_item.span, foreign_item.name);
 
@@ -526,11 +552,13 @@
 
 pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics) {
     for param in &generics.ty_params {
+        visitor.visit_id(param.id);
         visitor.visit_name(param.span, param.name);
         walk_list!(visitor, visit_ty_param_bound, &param.bounds);
         walk_list!(visitor, visit_ty, &param.default);
     }
     walk_list!(visitor, visit_lifetime_def, &generics.lifetimes);
+    visitor.visit_id(generics.where_clause.id);
     walk_list!(visitor, visit_where_predicate, &generics.where_clause.predicates);
 }
 
@@ -557,6 +585,7 @@
                                                       ref path,
                                                       ref ty,
                                                       ..}) => {
+            visitor.visit_id(id);
             visitor.visit_path(path, id);
             visitor.visit_ty(ty);
         }
@@ -571,6 +600,7 @@
 
 pub fn walk_fn_decl<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: &'v FnDecl) {
     for argument in &function_declaration.inputs {
+        visitor.visit_id(argument.id);
         visitor.visit_pat(&argument.pat);
         visitor.visit_ty(&argument.ty)
     }
@@ -579,6 +609,7 @@
 
 pub fn walk_fn_decl_nopat<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: &'v FnDecl) {
     for argument in &function_declaration.inputs {
+        visitor.visit_id(argument.id);
         visitor.visit_ty(&argument.ty)
     }
     walk_fn_ret_ty(visitor, &function_declaration.output)
@@ -600,7 +631,9 @@
                                    function_kind: FnKind<'v>,
                                    function_declaration: &'v FnDecl,
                                    function_body: &'v Block,
-                                   _span: Span) {
+                                   _span: Span,
+                                   id: NodeId) {
+    visitor.visit_id(id);
     walk_fn_decl(visitor, function_declaration);
     walk_fn_kind(visitor, function_kind);
     visitor.visit_block(function_body)
@@ -611,10 +644,12 @@
     walk_list!(visitor, visit_attribute, &trait_item.attrs);
     match trait_item.node {
         ConstTraitItem(ref ty, ref default) => {
+            visitor.visit_id(trait_item.id);
             visitor.visit_ty(ty);
             walk_list!(visitor, visit_expr, default);
         }
         MethodTraitItem(ref sig, None) => {
+            visitor.visit_id(trait_item.id);
             visitor.visit_generics(&sig.generics);
             walk_fn_decl(visitor, &sig.decl);
         }
@@ -629,6 +664,7 @@
                              trait_item.id);
         }
         TypeTraitItem(ref bounds, ref default) => {
+            visitor.visit_id(trait_item.id);
             walk_list!(visitor, visit_ty_param_bound, bounds);
             walk_list!(visitor, visit_ty, default);
         }
@@ -641,6 +677,7 @@
     walk_list!(visitor, visit_attribute, &impl_item.attrs);
     match impl_item.node {
         ImplItemKind::Const(ref ty, ref expr) => {
+            visitor.visit_id(impl_item.id);
             visitor.visit_ty(ty);
             visitor.visit_expr(expr);
         }
@@ -655,16 +692,19 @@
                              impl_item.id);
         }
         ImplItemKind::Type(ref ty) => {
+            visitor.visit_id(impl_item.id);
             visitor.visit_ty(ty);
         }
     }
 }
 
 pub fn walk_struct_def<'v, V: Visitor<'v>>(visitor: &mut V, struct_definition: &'v VariantData) {
+    visitor.visit_id(struct_definition.id());
     walk_list!(visitor, visit_struct_field, struct_definition.fields());
 }
 
 pub fn walk_struct_field<'v, V: Visitor<'v>>(visitor: &mut V, struct_field: &'v StructField) {
+    visitor.visit_id(struct_field.id);
     visitor.visit_vis(&struct_field.vis);
     visitor.visit_name(struct_field.span, struct_field.name);
     visitor.visit_ty(&struct_field.ty);
@@ -672,14 +712,20 @@
 }
 
 pub fn walk_block<'v, V: Visitor<'v>>(visitor: &mut V, block: &'v Block) {
+    visitor.visit_id(block.id);
     walk_list!(visitor, visit_stmt, &block.stmts);
     walk_list!(visitor, visit_expr, &block.expr);
 }
 
 pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt) {
     match statement.node {
-        StmtDecl(ref declaration, _) => visitor.visit_decl(declaration),
-        StmtExpr(ref expression, _) | StmtSemi(ref expression, _) => {
+        StmtDecl(ref declaration, id) => {
+            visitor.visit_id(id);
+            visitor.visit_decl(declaration)
+        }
+        StmtExpr(ref expression, id) |
+        StmtSemi(ref expression, id) => {
+            visitor.visit_id(id);
             visitor.visit_expr(expression)
         }
     }
@@ -693,6 +739,7 @@
 }
 
 pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
+    visitor.visit_id(expression.id);
     match expression.node {
         ExprBox(ref subexpression) => {
             visitor.visit_expr(subexpression)
@@ -815,11 +862,12 @@
 
 pub fn walk_vis<'v, V: Visitor<'v>>(visitor: &mut V, vis: &'v Visibility) {
     if let Visibility::Restricted { ref path, id } = *vis {
+        visitor.visit_id(id);
         visitor.visit_path(path, id)
     }
 }
 
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, PartialEq, Eq)]
 pub struct IdRange {
     pub min: NodeId,
     pub max: NodeId,
@@ -837,15 +885,17 @@
         self.min >= self.max
     }
 
+    pub fn contains(&self, id: NodeId) -> bool {
+        id >= self.min && id < self.max
+    }
+
     pub fn add(&mut self, id: NodeId) {
         self.min = cmp::min(self.min, id);
         self.max = cmp::max(self.max, id + 1);
     }
+
 }
 
-pub trait IdVisitingOperation {
-    fn visit_id(&mut self, node_id: NodeId);
-}
 
 pub struct IdRangeComputingVisitor {
     pub result: IdRange,
@@ -861,181 +911,12 @@
     }
 }
 
-impl IdVisitingOperation for IdRangeComputingVisitor {
+impl<'v> Visitor<'v> for IdRangeComputingVisitor {
     fn visit_id(&mut self, id: NodeId) {
         self.result.add(id);
     }
 }
 
-pub struct IdVisitor<'a, O: 'a> {
-    operation: &'a mut O,
-
-    // In general, the id visitor visits the contents of an item, but
-    // not including nested trait/impl items, nor other nested items.
-    // The base visitor itself always skips nested items, but not
-    // trait/impl items. This means in particular that if you start by
-    // visiting a trait or an impl, you should not visit the
-    // trait/impl items respectively.  This is handled by setting
-    // `skip_members` to true when `visit_item` is on the stack. This
-    // way, if the user begins by calling `visit_trait_item`, we will
-    // visit the trait item, but if they begin with `visit_item`, we
-    // won't visit the (nested) trait items.
-    skip_members: bool,
-}
-
-impl<'a, O: IdVisitingOperation> IdVisitor<'a, O> {
-    pub fn new(operation: &'a mut O) -> IdVisitor<'a, O> {
-        IdVisitor { operation: operation, skip_members: false }
-    }
-
-    fn visit_generics_helper(&mut self, generics: &Generics) {
-        for type_parameter in generics.ty_params.iter() {
-            self.operation.visit_id(type_parameter.id)
-        }
-        for lifetime in &generics.lifetimes {
-            self.operation.visit_id(lifetime.lifetime.id)
-        }
-    }
-}
-
-impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> {
-    fn visit_mod(&mut self, module: &Mod, _: Span, node_id: NodeId) {
-        self.operation.visit_id(node_id);
-        walk_mod(self, module)
-    }
-
-    fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
-        self.operation.visit_id(foreign_item.id);
-        walk_foreign_item(self, foreign_item)
-    }
-
-    fn visit_item(&mut self, item: &Item) {
-        assert!(!self.skip_members);
-        self.skip_members = true;
-
-        self.operation.visit_id(item.id);
-        match item.node {
-            ItemUse(ref view_path) => {
-                match view_path.node {
-                    ViewPathSimple(_, _) |
-                    ViewPathGlob(_) => {}
-                    ViewPathList(_, ref paths) => {
-                        for path in paths {
-                            self.operation.visit_id(path.node.id())
-                        }
-                    }
-                }
-            }
-            _ => {}
-        }
-        walk_item(self, item);
-
-        self.skip_members = false;
-    }
-
-    fn visit_local(&mut self, local: &Local) {
-        self.operation.visit_id(local.id);
-        walk_local(self, local)
-    }
-
-    fn visit_block(&mut self, block: &Block) {
-        self.operation.visit_id(block.id);
-        walk_block(self, block)
-    }
-
-    fn visit_stmt(&mut self, statement: &Stmt) {
-        self.operation.visit_id(statement.node.id());
-        walk_stmt(self, statement)
-    }
-
-    fn visit_pat(&mut self, pattern: &Pat) {
-        self.operation.visit_id(pattern.id);
-        walk_pat(self, pattern)
-    }
-
-    fn visit_expr(&mut self, expression: &Expr) {
-        self.operation.visit_id(expression.id);
-        walk_expr(self, expression)
-    }
-
-    fn visit_ty(&mut self, typ: &Ty) {
-        self.operation.visit_id(typ.id);
-        walk_ty(self, typ)
-    }
-
-    fn visit_generics(&mut self, generics: &Generics) {
-        self.visit_generics_helper(generics);
-        walk_generics(self, generics)
-    }
-
-    fn visit_fn(&mut self,
-                function_kind: FnKind<'v>,
-                function_declaration: &'v FnDecl,
-                block: &'v Block,
-                span: Span,
-                node_id: NodeId) {
-        self.operation.visit_id(node_id);
-
-        match function_kind {
-            FnKind::ItemFn(_, generics, _, _, _, _, _) => {
-                self.visit_generics_helper(generics)
-            }
-            FnKind::Method(_, sig, _, _) => {
-                self.visit_generics_helper(&sig.generics)
-            }
-            FnKind::Closure(_) => {}
-        }
-
-        for argument in &function_declaration.inputs {
-            self.operation.visit_id(argument.id)
-        }
-
-        walk_fn(self, function_kind, function_declaration, block, span);
-    }
-
-    fn visit_struct_field(&mut self, struct_field: &StructField) {
-        self.operation.visit_id(struct_field.id);
-        walk_struct_field(self, struct_field)
-    }
-
-    fn visit_variant_data(&mut self,
-                          struct_def: &VariantData,
-                          _: Name,
-                          _: &Generics,
-                          _: NodeId,
-                          _: Span) {
-        self.operation.visit_id(struct_def.id());
-        walk_struct_def(self, struct_def);
-    }
-
-    fn visit_trait_item(&mut self, ti: &TraitItem) {
-        if !self.skip_members {
-            self.operation.visit_id(ti.id);
-            walk_trait_item(self, ti);
-        }
-    }
-
-    fn visit_impl_item(&mut self, ii: &ImplItem) {
-        if !self.skip_members {
-            self.operation.visit_id(ii.id);
-            walk_impl_item(self, ii);
-        }
-    }
-
-    fn visit_lifetime(&mut self, lifetime: &Lifetime) {
-        self.operation.visit_id(lifetime.id);
-    }
-
-    fn visit_lifetime_def(&mut self, def: &LifetimeDef) {
-        self.visit_lifetime(&def.lifetime);
-    }
-
-    fn visit_trait_ref(&mut self, trait_ref: &TraitRef) {
-        self.operation.visit_id(trait_ref.ref_id);
-        walk_trait_ref(self, trait_ref);
-    }
-}
-
 /// Computes the id range for a single fn body, ignoring nested items.
 pub fn compute_id_range_for_fn_body(fk: FnKind,
                                     decl: &FnDecl,
@@ -1043,8 +924,7 @@
                                     sp: Span,
                                     id: NodeId)
                                     -> IdRange {
-    let mut visitor = IdRangeComputingVisitor { result: IdRange::max() };
-    let mut id_visitor = IdVisitor::new(&mut visitor);
-    id_visitor.visit_fn(fk, decl, body, sp, id);
-    id_visitor.operation.result
+    let mut visitor = IdRangeComputingVisitor::new();
+    visitor.visit_fn(fk, decl, body, sp, id);
+    visitor.result()
 }
diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs
index 693d7a2..b3f222b 100644
--- a/src/librustc/hir/map/collector.rs
+++ b/src/librustc/hir/map/collector.rs
@@ -197,7 +197,7 @@
     fn visit_fn(&mut self, fk: intravisit::FnKind<'ast>, fd: &'ast FnDecl,
                 b: &'ast Block, s: Span, id: NodeId) {
         assert_eq!(self.parent_node, id);
-        intravisit::walk_fn(self, fk, fd, b, s);
+        intravisit::walk_fn(self, fk, fd, b, s, id);
     }
 
     fn visit_block(&mut self, block: &'ast Block) {
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index 960e32a..aed3613 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -32,6 +32,7 @@
 
 use arena::TypedArena;
 use std::cell::RefCell;
+use std::cmp;
 use std::io;
 use std::mem;
 
@@ -127,7 +128,10 @@
             EntryStructCtor(id, _) => id,
             EntryLifetime(id, _) => id,
             EntryTyParam(id, _) => id,
-            _ => return None
+
+            NotPresent |
+            RootCrate |
+            RootInlinedParent(_) => return None,
         })
     }
 
@@ -196,6 +200,10 @@
     map: RefCell<Vec<MapEntry<'ast>>>,
 
     definitions: RefCell<Definitions>,
+
+    /// All NodeIds that are numerically greater or equal to this value come
+    /// from inlined items.
+    local_node_id_watermark: NodeId,
 }
 
 impl<'ast> Map<'ast> {
@@ -550,6 +558,13 @@
         }
     }
 
+    pub fn expect_inlined_item(&self, id: NodeId) -> &'ast InlinedItem {
+        match self.find_entry(id) {
+            Some(RootInlinedParent(inlined_item)) => inlined_item,
+            _ => bug!("expected inlined item, found {}", self.node_to_string(id)),
+        }
+    }
+
     /// Returns the name associated with the given NodeId's AST.
     pub fn name(&self, id: NodeId) -> Name {
         match self.get(id) {
@@ -649,6 +664,10 @@
     pub fn node_to_user_string(&self, id: NodeId) -> String {
         node_id_to_string(self, id, false)
     }
+
+    pub fn is_inlined(&self, id: NodeId) -> bool {
+        id >= self.local_node_id_watermark
+    }
 }
 
 pub struct NodesMatchingSuffix<'a, 'ast:'a> {
@@ -765,13 +784,37 @@
 }
 
 /// A Folder that updates IDs and Span's according to fold_ops.
-struct IdAndSpanUpdater<F> {
-    fold_ops: F
+pub struct IdAndSpanUpdater<F> {
+    fold_ops: F,
+    min_id_assigned: NodeId,
+    max_id_assigned: NodeId,
+}
+
+impl<F: FoldOps> IdAndSpanUpdater<F> {
+    pub fn new(fold_ops: F) -> IdAndSpanUpdater<F> {
+        IdAndSpanUpdater {
+            fold_ops: fold_ops,
+            min_id_assigned: ::std::u32::MAX,
+            max_id_assigned: ::std::u32::MIN,
+        }
+    }
+
+    pub fn id_range(&self) -> intravisit::IdRange {
+        intravisit::IdRange {
+            min: self.min_id_assigned,
+            max: self.max_id_assigned + 1,
+        }
+    }
 }
 
 impl<F: FoldOps> Folder for IdAndSpanUpdater<F> {
     fn new_id(&mut self, id: NodeId) -> NodeId {
-        self.fold_ops.new_id(id)
+        let id = self.fold_ops.new_id(id);
+
+        self.min_id_assigned = cmp::min(self.min_id_assigned, id);
+        self.max_id_assigned = cmp::max(self.max_id_assigned, id);
+
+        id
     }
 
     fn new_span(&mut self, span: Span) -> Span {
@@ -802,11 +845,14 @@
               entries, vector_length, (entries as f64 / vector_length as f64) * 100.);
     }
 
+    let local_node_id_watermark = map.len() as NodeId;
+
     Map {
         forest: forest,
         dep_graph: forest.dep_graph.clone(),
         map: RefCell::new(map),
         definitions: RefCell::new(definitions),
+        local_node_id_watermark: local_node_id_watermark
     }
 }
 
@@ -818,7 +864,7 @@
                                           ii: InlinedItem,
                                           fold_ops: F)
                                           -> &'ast InlinedItem {
-    let mut fld = IdAndSpanUpdater { fold_ops: fold_ops };
+    let mut fld = IdAndSpanUpdater::new(fold_ops);
     let ii = match ii {
         II::Item(i) => II::Item(i.map(|i| fld.fold_item(i))),
         II::TraitItem(d, ti) => {
@@ -835,6 +881,12 @@
     let ii = map.forest.inlined_items.alloc(ii);
     let ii_parent_id = fld.new_id(DUMMY_NODE_ID);
 
+    // Assert that the ii_parent_id is the last NodeId in our reserved range
+    assert!(ii_parent_id == fld.max_id_assigned);
+    // Assert that we did not violate the invariant that all inlined HIR items
+    // have NodeIds greater than or equal to `local_node_id_watermark`
+    assert!(fld.min_id_assigned >= map.local_node_id_watermark);
+
     let defs = &mut *map.definitions.borrow_mut();
     let mut def_collector = DefCollector::extend(ii_parent_id,
                                                  parent_def_path.clone(),
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 655f80e..20bf4f7 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -1362,9 +1362,9 @@
 /// TraitRef's appear in impls.
 ///
 /// resolve maps each TraitRef's ref_id to its defining trait; that's all
-/// that the ref_id is for. The impl_id maps to the "self type" of this impl.
-/// If this impl is an ItemImpl, the impl_id is redundant (it could be the
-/// same as the impl's node id).
+/// that the ref_id is for. Note that ref_id's value is not the NodeId of the
+/// trait being referred to but just a unique NodeId that serves as a key
+/// within the DefMap.
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct TraitRef {
     pub path: Path,
diff --git a/src/librustc/infer/bivariate.rs b/src/librustc/infer/bivariate.rs
index 96b14a6..125f815 100644
--- a/src/librustc/infer/bivariate.rs
+++ b/src/librustc/infer/bivariate.rs
@@ -32,22 +32,27 @@
 use ty::TyVar;
 use ty::relate::{Relate, RelateResult, TypeRelation};
 
-pub struct Bivariate<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
-    fields: CombineFields<'a, 'gcx, 'tcx>
+pub struct Bivariate<'combine, 'infcx: 'combine, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
+    fields: &'combine mut CombineFields<'infcx, 'gcx, 'tcx>,
+    a_is_expected: bool,
 }
 
-impl<'a, 'gcx, 'tcx> Bivariate<'a, 'gcx, 'tcx> {
-    pub fn new(fields: CombineFields<'a, 'gcx, 'tcx>) -> Bivariate<'a, 'gcx, 'tcx> {
-        Bivariate { fields: fields }
+impl<'combine, 'infcx, 'gcx, 'tcx> Bivariate<'combine, 'infcx, 'gcx, 'tcx> {
+    pub fn new(fields: &'combine mut CombineFields<'infcx, 'gcx, 'tcx>, a_is_expected: bool)
+        -> Bivariate<'combine, 'infcx, 'gcx, 'tcx>
+    {
+        Bivariate { fields: fields, a_is_expected: a_is_expected }
     }
 }
 
-impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Bivariate<'a, 'gcx, 'tcx> {
+impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
+    for Bivariate<'combine, 'infcx, 'gcx, 'tcx>
+{
     fn tag(&self) -> &'static str { "Bivariate" }
 
-    fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { self.fields.tcx() }
+    fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() }
 
-    fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
+    fn a_is_expected(&self) -> bool { self.a_is_expected }
 
     fn relate_with_variance<T: Relate<'tcx>>(&mut self,
                                              variance: ty::Variance,
@@ -86,12 +91,12 @@
             }
 
             (&ty::TyInfer(TyVar(a_id)), _) => {
-                self.fields.instantiate(b, BiTo, a_id)?;
+                self.fields.instantiate(b, BiTo, a_id, self.a_is_expected)?;
                 Ok(a)
             }
 
             (_, &ty::TyInfer(TyVar(b_id))) => {
-                self.fields.instantiate(a, BiTo, b_id)?;
+                self.fields.instantiate(a, BiTo, b_id, self.a_is_expected)?;
                 Ok(a)
             }
 
diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs
index c9235d0..b4818f9 100644
--- a/src/librustc/infer/combine.rs
+++ b/src/librustc/infer/combine.rs
@@ -52,21 +52,20 @@
 use syntax_pos::Span;
 
 #[derive(Clone)]
-pub struct CombineFields<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
-    pub infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
-    pub a_is_expected: bool,
+pub struct CombineFields<'infcx, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
+    pub infcx: &'infcx InferCtxt<'infcx, 'gcx, 'tcx>,
     pub trace: TypeTrace<'tcx>,
     pub cause: Option<ty::relate::Cause>,
     pub obligations: PredicateObligations<'tcx>,
 }
 
-impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
+impl<'infcx, 'gcx, 'tcx> InferCtxt<'infcx, 'gcx, 'tcx> {
     pub fn super_combine_tys<R>(&self,
                                 relation: &mut R,
                                 a: Ty<'tcx>,
                                 b: Ty<'tcx>)
                                 -> RelateResult<'tcx, Ty<'tcx>>
-        where R: TypeRelation<'a, 'gcx, 'tcx>
+        where R: TypeRelation<'infcx, 'gcx, 'tcx>
     {
         let a_is_expected = relation.a_is_expected();
 
@@ -150,42 +149,36 @@
     }
 }
 
-impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
-    pub fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {
+impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> {
+    pub fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> {
         self.infcx.tcx
     }
 
-    pub fn switch_expected(&self) -> CombineFields<'a, 'gcx, 'tcx> {
-        CombineFields {
-            a_is_expected: !self.a_is_expected,
-            ..(*self).clone()
-        }
+    pub fn equate<'a>(&'a mut self, a_is_expected: bool) -> Equate<'a, 'infcx, 'gcx, 'tcx> {
+        Equate::new(self, a_is_expected)
     }
 
-    pub fn equate(&self) -> Equate<'a, 'gcx, 'tcx> {
-        Equate::new(self.clone())
+    pub fn bivariate<'a>(&'a mut self, a_is_expected: bool) -> Bivariate<'a, 'infcx, 'gcx, 'tcx> {
+        Bivariate::new(self, a_is_expected)
     }
 
-    pub fn bivariate(&self) -> Bivariate<'a, 'gcx, 'tcx> {
-        Bivariate::new(self.clone())
+    pub fn sub<'a>(&'a mut self, a_is_expected: bool) -> Sub<'a, 'infcx, 'gcx, 'tcx> {
+        Sub::new(self, a_is_expected)
     }
 
-    pub fn sub(&self) -> Sub<'a, 'gcx, 'tcx> {
-        Sub::new(self.clone())
+    pub fn lub<'a>(&'a mut self, a_is_expected: bool) -> Lub<'a, 'infcx, 'gcx, 'tcx> {
+        Lub::new(self, a_is_expected)
     }
 
-    pub fn lub(&self) -> Lub<'a, 'gcx, 'tcx> {
-        Lub::new(self.clone())
+    pub fn glb<'a>(&'a mut self, a_is_expected: bool) -> Glb<'a, 'infcx, 'gcx, 'tcx> {
+        Glb::new(self, a_is_expected)
     }
 
-    pub fn glb(&self) -> Glb<'a, 'gcx, 'tcx> {
-        Glb::new(self.clone())
-    }
-
-    pub fn instantiate(&self,
+    pub fn instantiate(&mut self,
                        a_ty: Ty<'tcx>,
                        dir: RelationDir,
-                       b_vid: ty::TyVid)
+                       b_vid: ty::TyVid,
+                       a_is_expected: bool)
                        -> RelateResult<'tcx, ()>
     {
         let mut stack = Vec::new();
@@ -255,10 +248,11 @@
             // to associate causes/spans with each of the relations in
             // the stack to get this right.
             match dir {
-                BiTo => self.bivariate().relate(&a_ty, &b_ty),
-                EqTo => self.equate().relate(&a_ty, &b_ty),
-                SubtypeOf => self.sub().relate(&a_ty, &b_ty),
-                SupertypeOf => self.sub().relate_with_variance(ty::Contravariant, &a_ty, &b_ty),
+                BiTo => self.bivariate(a_is_expected).relate(&a_ty, &b_ty),
+                EqTo => self.equate(a_is_expected).relate(&a_ty, &b_ty),
+                SubtypeOf => self.sub(a_is_expected).relate(&a_ty, &b_ty),
+                SupertypeOf => self.sub(a_is_expected).relate_with_variance(
+                    ty::Contravariant, &a_ty, &b_ty),
             }?;
         }
 
diff --git a/src/librustc/infer/equate.rs b/src/librustc/infer/equate.rs
index 408f22c..e06f730 100644
--- a/src/librustc/infer/equate.rs
+++ b/src/librustc/infer/equate.rs
@@ -15,29 +15,29 @@
 use ty::{self, Ty, TyCtxt};
 use ty::TyVar;
 use ty::relate::{Relate, RelateResult, TypeRelation};
-use traits::PredicateObligations;
 
 /// Ensures `a` is made equal to `b`. Returns `a` on success.
-pub struct Equate<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
-    fields: CombineFields<'a, 'gcx, 'tcx>
+pub struct Equate<'combine, 'infcx: 'combine, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
+    fields: &'combine mut CombineFields<'infcx, 'gcx, 'tcx>,
+    a_is_expected: bool,
 }
 
-impl<'a, 'gcx, 'tcx> Equate<'a, 'gcx, 'tcx> {
-    pub fn new(fields: CombineFields<'a, 'gcx, 'tcx>) -> Equate<'a, 'gcx, 'tcx> {
-        Equate { fields: fields }
-    }
-
-    pub fn obligations(self) -> PredicateObligations<'tcx> {
-        self.fields.obligations
+impl<'combine, 'infcx, 'gcx, 'tcx> Equate<'combine, 'infcx, 'gcx, 'tcx> {
+    pub fn new(fields: &'combine mut CombineFields<'infcx, 'gcx, 'tcx>, a_is_expected: bool)
+        -> Equate<'combine, 'infcx, 'gcx, 'tcx>
+    {
+        Equate { fields: fields, a_is_expected: a_is_expected }
     }
 }
 
-impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Equate<'a, 'gcx, 'tcx> {
+impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
+    for Equate<'combine, 'infcx, 'gcx, 'tcx>
+{
     fn tag(&self) -> &'static str { "Equate" }
 
-    fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { self.fields.tcx() }
+    fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() }
 
-    fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
+    fn a_is_expected(&self) -> bool { self.a_is_expected }
 
     fn relate_with_variance<T: Relate<'tcx>>(&mut self,
                                              _: ty::Variance,
@@ -63,12 +63,12 @@
             }
 
             (&ty::TyInfer(TyVar(a_id)), _) => {
-                self.fields.instantiate(b, EqTo, a_id)?;
+                self.fields.instantiate(b, EqTo, a_id, self.a_is_expected)?;
                 Ok(a)
             }
 
             (_, &ty::TyInfer(TyVar(b_id))) => {
-                self.fields.instantiate(a, EqTo, b_id)?;
+                self.fields.instantiate(a, EqTo, b_id, self.a_is_expected)?;
                 Ok(a)
             }
 
@@ -93,7 +93,7 @@
                   -> RelateResult<'tcx, ty::Binder<T>>
         where T: Relate<'tcx>
     {
-        self.fields.higher_ranked_sub(a, b)?;
-        self.fields.higher_ranked_sub(b, a)
+        self.fields.higher_ranked_sub(a, b, self.a_is_expected)?;
+        self.fields.higher_ranked_sub(b, a, self.a_is_expected)
     }
 }
diff --git a/src/librustc/infer/error_reporting.rs b/src/librustc/infer/error_reporting.rs
index 96ecad6..511cc32 100644
--- a/src/librustc/infer/error_reporting.rs
+++ b/src/librustc/infer/error_reporting.rs
@@ -83,7 +83,7 @@
 use infer::{self, TypeOrigin};
 use middle::region;
 use ty::subst;
-use ty::{self, Ty, TyCtxt, TypeFoldable};
+use ty::{self, TyCtxt, TypeFoldable};
 use ty::{Region, ReFree};
 use ty::error::TypeError;
 
@@ -462,52 +462,6 @@
         }
     }
 
-    fn report_type_error(&self,
-                         trace: TypeTrace<'tcx>,
-                         terr: &TypeError<'tcx>)
-                         -> DiagnosticBuilder<'tcx> {
-        let (expected, found) = match self.values_str(&trace.values) {
-            Some(v) => v,
-            None => {
-                return self.tcx.sess.diagnostic().struct_dummy(); /* derived error */
-            }
-        };
-
-        let is_simple_error = if let &TypeError::Sorts(ref values) = terr {
-            values.expected.is_primitive() && values.found.is_primitive()
-        } else {
-            false
-        };
-
-        let mut err = struct_span_err!(self.tcx.sess,
-                                       trace.origin.span(),
-                                       E0308,
-                                       "{}",
-                                       trace.origin);
-
-        if !is_simple_error || check_old_school() {
-            err.note_expected_found(&"type", &expected, &found);
-        }
-
-        err.span_label(trace.origin.span(), &terr);
-
-        self.check_and_note_conflicting_crates(&mut err, terr, trace.origin.span());
-
-        match trace.origin {
-            TypeOrigin::MatchExpressionArm(_, arm_span, source) => match source {
-                hir::MatchSource::IfLetDesugar{..} => {
-                    err.span_note(arm_span, "`if let` arm with an incompatible type");
-                }
-                _ => {
-                    err.span_note(arm_span, "match arm with an incompatible type");
-                }
-            },
-            _ => ()
-        }
-
-        err
-    }
-
     /// Adds a note if the types come from similarly named crates
     fn check_and_note_conflicting_crates(&self,
                                          err: &mut DiagnosticBuilder,
@@ -550,42 +504,102 @@
         }
     }
 
+    fn note_error_origin(&self,
+                         err: &mut DiagnosticBuilder<'tcx>,
+                         origin: &TypeOrigin)
+    {
+        match origin {
+            &TypeOrigin::MatchExpressionArm(_, arm_span, source) => match source {
+                hir::MatchSource::IfLetDesugar {..} => {
+                    err.span_note(arm_span, "`if let` arm with an incompatible type");
+                }
+                _ => {
+                    err.span_note(arm_span, "match arm with an incompatible type");
+                }
+            },
+            _ => ()
+        }
+    }
+
+    pub fn note_type_err(&self,
+                         diag: &mut DiagnosticBuilder<'tcx>,
+                         origin: TypeOrigin,
+                         values: Option<ValuePairs<'tcx>>,
+                         terr: &TypeError<'tcx>)
+    {
+        let expected_found = match values {
+            None => None,
+            Some(values) => match self.values_str(&values) {
+                Some((expected, found)) => Some((expected, found)),
+                None => {
+                    // Derived error. Cancel the emitter.
+                    self.tcx.sess.diagnostic().cancel(diag);
+                    return
+                }
+            }
+        };
+
+        let span = origin.span();
+
+        let mut is_simple_error = false;
+
+        if let Some((expected, found)) = expected_found {
+            is_simple_error = if let &TypeError::Sorts(ref values) = terr {
+                values.expected.is_primitive() && values.found.is_primitive()
+            } else {
+                false
+            };
+
+            if !is_simple_error || check_old_school() {
+                diag.note_expected_found(&"type", &expected, &found);
+            }
+        }
+
+        if !is_simple_error && check_old_school() {
+            diag.span_note(span, &format!("{}", terr));
+        } else {
+            diag.span_label(span, &terr);
+        }
+
+        self.note_error_origin(diag, &origin);
+        self.check_and_note_conflicting_crates(diag, terr, span);
+        self.tcx.note_and_explain_type_err(diag, terr, span);
+    }
+
     pub fn report_and_explain_type_error(&self,
                                          trace: TypeTrace<'tcx>,
                                          terr: &TypeError<'tcx>)
-                                         -> DiagnosticBuilder<'tcx> {
-        let span = trace.origin.span();
-        let mut err = self.report_type_error(trace, terr);
-        self.tcx.note_and_explain_type_err(&mut err, terr, span);
-        err
+                                         -> DiagnosticBuilder<'tcx>
+    {
+        // FIXME: do we want to use a different error code for each origin?
+        let mut diag = struct_span_err!(
+            self.tcx.sess, trace.origin.span(), E0308,
+            "{}", trace.origin.as_failure_str()
+        );
+        self.note_type_err(&mut diag, trace.origin, Some(trace.values), terr);
+        diag
     }
 
-    /// Returns a string of the form "expected `{}`, found `{}`", or None if this is a derived
-    /// error.
+    /// Returns a string of the form "expected `{}`, found `{}`".
     fn values_str(&self, values: &ValuePairs<'tcx>) -> Option<(String, String)> {
         match *values {
             infer::Types(ref exp_found) => self.expected_found_str(exp_found),
             infer::TraitRefs(ref exp_found) => self.expected_found_str(exp_found),
-            infer::PolyTraitRefs(ref exp_found) => self.expected_found_str(exp_found)
+            infer::PolyTraitRefs(ref exp_found) => self.expected_found_str(exp_found),
         }
     }
 
-    fn expected_found_str<T: fmt::Display + Resolvable<'tcx> + TypeFoldable<'tcx>>(
+    fn expected_found_str<T: fmt::Display + TypeFoldable<'tcx>>(
         &self,
         exp_found: &ty::error::ExpectedFound<T>)
         -> Option<(String, String)>
     {
-        let expected = exp_found.expected.resolve(self);
-        if expected.references_error() {
+        let exp_found = self.resolve_type_vars_if_possible(exp_found);
+        if exp_found.references_error() {
             return None;
         }
 
-        let found = exp_found.found.resolve(self);
-        if found.references_error() {
-            return None;
-        }
-
-        Some((format!("{}", expected), format!("{}", found)))
+        Some((format!("{}", exp_found.expected), format!("{}", exp_found.found)))
     }
 
     fn report_generic_bound_failure(&self,
@@ -1608,59 +1622,21 @@
     fn note_region_origin(&self, err: &mut DiagnosticBuilder, origin: &SubregionOrigin<'tcx>) {
         match *origin {
             infer::Subtype(ref trace) => {
-                let desc = match trace.origin {
-                    TypeOrigin::Misc(_) => {
-                        "types are compatible"
-                    }
-                    TypeOrigin::MethodCompatCheck(_) => {
-                        "method type is compatible with trait"
-                    }
-                    TypeOrigin::ExprAssignable(_) => {
-                        "expression is assignable"
-                    }
-                    TypeOrigin::RelateTraitRefs(_) => {
-                        "traits are compatible"
-                    }
-                    TypeOrigin::RelateSelfType(_) => {
-                        "self type matches impl self type"
-                    }
-                    TypeOrigin::RelateOutputImplTypes(_) => {
-                        "trait type parameters matches those \
-                                 specified on the impl"
-                    }
-                    TypeOrigin::MatchExpressionArm(_, _, _) => {
-                        "match arms have compatible types"
-                    }
-                    TypeOrigin::IfExpression(_) => {
-                        "if and else have compatible types"
-                    }
-                    TypeOrigin::IfExpressionWithNoElse(_) => {
-                        "if may be missing an else clause"
-                    }
-                    TypeOrigin::RangeExpression(_) => {
-                        "start and end of range have compatible types"
-                    }
-                    TypeOrigin::EquatePredicate(_) => {
-                        "equality where clause is satisfied"
-                    }
-                };
+                if let Some((expected, found)) = self.values_str(&trace.values) {
+                    // FIXME: do we want a "the" here?
+                    err.span_note(
+                        trace.origin.span(),
+                        &format!("...so that {} (expected {}, found {})",
+                                 trace.origin.as_requirement_str(), expected, found));
+                } else {
+                    // FIXME: this really should be handled at some earlier stage. Our
+                    // handling of region checking when type errors are present is
+                    // *terrible*.
 
-                match self.values_str(&trace.values) {
-                    Some((expected, found)) => {
-                        err.span_note(
-                            trace.origin.span(),
-                            &format!("...so that {} (expected {}, found {})",
-                                    desc, expected, found));
-                    }
-                    None => {
-                        // Really should avoid printing this error at
-                        // all, since it is derived, but that would
-                        // require more refactoring than I feel like
-                        // doing right now. - nmatsakis
-                        err.span_note(
-                            trace.origin.span(),
-                            &format!("...so that {}", desc));
-                    }
+                    err.span_note(
+                        trace.origin.span(),
+                        &format!("...so that {}",
+                                 trace.origin.as_requirement_str()));
                 }
             }
             infer::Reborrow(span) => {
@@ -1803,32 +1779,6 @@
     }
 }
 
-pub trait Resolvable<'tcx> {
-    fn resolve<'a, 'gcx>(&self, infcx: &InferCtxt<'a, 'gcx, 'tcx>) -> Self;
-}
-
-impl<'tcx> Resolvable<'tcx> for Ty<'tcx> {
-    fn resolve<'a, 'gcx>(&self, infcx: &InferCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
-        infcx.resolve_type_vars_if_possible(self)
-    }
-}
-
-impl<'tcx> Resolvable<'tcx> for ty::TraitRef<'tcx> {
-    fn resolve<'a, 'gcx>(&self, infcx: &InferCtxt<'a, 'gcx, 'tcx>)
-                         -> ty::TraitRef<'tcx> {
-        infcx.resolve_type_vars_if_possible(self)
-    }
-}
-
-impl<'tcx> Resolvable<'tcx> for ty::PolyTraitRef<'tcx> {
-    fn resolve<'a, 'gcx>(&self,
-                         infcx: &InferCtxt<'a, 'gcx, 'tcx>)
-                         -> ty::PolyTraitRef<'tcx>
-    {
-        infcx.resolve_type_vars_if_possible(self)
-    }
-}
-
 fn lifetimes_in_scope<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                                       scope_id: ast::NodeId)
                                       -> Vec<hir::LifetimeDef> {
diff --git a/src/librustc/infer/glb.rs b/src/librustc/infer/glb.rs
index b7085f0..5dd85a3 100644
--- a/src/librustc/infer/glb.rs
+++ b/src/librustc/infer/glb.rs
@@ -15,29 +15,29 @@
 
 use ty::{self, Ty, TyCtxt};
 use ty::relate::{Relate, RelateResult, TypeRelation};
-use traits::PredicateObligations;
 
 /// "Greatest lower bound" (common subtype)
-pub struct Glb<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
-    fields: CombineFields<'a, 'gcx, 'tcx>
+pub struct Glb<'combine, 'infcx: 'combine, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
+    fields: &'combine mut CombineFields<'infcx, 'gcx, 'tcx>,
+    a_is_expected: bool,
 }
 
-impl<'a, 'gcx, 'tcx> Glb<'a, 'gcx, 'tcx> {
-    pub fn new(fields: CombineFields<'a, 'gcx, 'tcx>) -> Glb<'a, 'gcx, 'tcx> {
-        Glb { fields: fields }
-    }
-
-    pub fn obligations(self) -> PredicateObligations<'tcx> {
-        self.fields.obligations
+impl<'combine, 'infcx, 'gcx, 'tcx> Glb<'combine, 'infcx, 'gcx, 'tcx> {
+    pub fn new(fields: &'combine mut CombineFields<'infcx, 'gcx, 'tcx>, a_is_expected: bool)
+        -> Glb<'combine, 'infcx, 'gcx, 'tcx>
+    {
+        Glb { fields: fields, a_is_expected: a_is_expected }
     }
 }
 
-impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Glb<'a, 'gcx, 'tcx> {
+impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
+    for Glb<'combine, 'infcx, 'gcx, 'tcx>
+{
     fn tag(&self) -> &'static str { "Glb" }
 
-    fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { self.fields.tcx() }
+    fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() }
 
-    fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
+    fn a_is_expected(&self) -> bool { self.a_is_expected }
 
     fn relate_with_variance<T: Relate<'tcx>>(&mut self,
                                              variance: ty::Variance,
@@ -46,10 +46,10 @@
                                              -> RelateResult<'tcx, T>
     {
         match variance {
-            ty::Invariant => self.fields.equate().relate(a, b),
+            ty::Invariant => self.fields.equate(self.a_is_expected).relate(a, b),
             ty::Covariant => self.relate(a, b),
-            ty::Bivariant => self.fields.bivariate().relate(a, b),
-            ty::Contravariant => self.fields.lub().relate(a, b),
+            ty::Bivariant => self.fields.bivariate(self.a_is_expected).relate(a, b),
+            ty::Contravariant => self.fields.lub(self.a_is_expected).relate(a, b),
         }
     }
 
@@ -71,17 +71,19 @@
                   -> RelateResult<'tcx, ty::Binder<T>>
         where T: Relate<'tcx>
     {
-        self.fields.higher_ranked_glb(a, b)
+        self.fields.higher_ranked_glb(a, b, self.a_is_expected)
     }
 }
 
-impl<'a, 'gcx, 'tcx> LatticeDir<'a, 'gcx, 'tcx> for Glb<'a, 'gcx, 'tcx> {
-    fn infcx(&self) -> &'a InferCtxt<'a, 'gcx, 'tcx> {
+impl<'combine, 'infcx, 'gcx, 'tcx> LatticeDir<'infcx, 'gcx, 'tcx>
+    for Glb<'combine, 'infcx, 'gcx, 'tcx>
+{
+    fn infcx(&self) -> &'infcx InferCtxt<'infcx, 'gcx, 'tcx> {
         self.fields.infcx
     }
 
-    fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
-        let mut sub = self.fields.sub();
+    fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
+        let mut sub = self.fields.sub(self.a_is_expected);
         sub.relate(&v, &a)?;
         sub.relate(&v, &b)?;
         Ok(())
diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs
index 03a0991..743d613 100644
--- a/src/librustc/infer/higher_ranked/mod.rs
+++ b/src/librustc/infer/higher_ranked/mod.rs
@@ -40,7 +40,7 @@
 }
 
 impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
-    pub fn higher_ranked_sub<T>(&self, a: &Binder<T>, b: &Binder<T>)
+    pub fn higher_ranked_sub<T>(&mut self, a: &Binder<T>, b: &Binder<T>, a_is_expected: bool)
                                 -> RelateResult<'tcx, Binder<T>>
         where T: Relate<'tcx>
     {
@@ -77,11 +77,11 @@
             debug!("b_prime={:?}", b_prime);
 
             // Compare types now that bound regions have been replaced.
-            let result = self.sub().relate(&a_prime, &b_prime)?;
+            let result = self.sub(a_is_expected).relate(&a_prime, &b_prime)?;
 
             // Presuming type comparison succeeds, we need to check
             // that the skolemized regions do not "leak".
-            self.infcx.leak_check(!self.a_is_expected, span, &skol_map, snapshot)?;
+            self.infcx.leak_check(!a_is_expected, span, &skol_map, snapshot)?;
 
             // We are finished with the skolemized regions now so pop
             // them off.
@@ -106,10 +106,11 @@
     /// NB. It should not happen that there are LBR appearing in `U`
     /// that do not appear in `T`. If that happens, those regions are
     /// unconstrained, and this routine replaces them with `'static`.
-    pub fn higher_ranked_match<T, U>(&self,
+    pub fn higher_ranked_match<T, U>(&mut self,
                                      span: Span,
                                      a_pair: &Binder<(T, U)>,
-                                     b_match: &T)
+                                     b_match: &T,
+                                     a_is_expected: bool)
                                      -> RelateResult<'tcx, HrMatchResult<U>>
         where T: Relate<'tcx>,
               U: TypeFoldable<'tcx>
@@ -129,7 +130,7 @@
             debug!("higher_ranked_match: skol_map={:?}", skol_map);
 
             // Equate types now that bound regions have been replaced.
-            try!(self.equate().relate(&a_match, &b_match));
+            try!(self.equate(a_is_expected).relate(&a_match, &b_match));
 
             // Map each skolemized region to a vector of other regions that it
             // must be equated with. (Note that this vector may include other
@@ -221,7 +222,7 @@
         });
     }
 
-    pub fn higher_ranked_lub<T>(&self, a: &Binder<T>, b: &Binder<T>)
+    pub fn higher_ranked_lub<T>(&mut self, a: &Binder<T>, b: &Binder<T>, a_is_expected: bool)
                                 -> RelateResult<'tcx, Binder<T>>
         where T: Relate<'tcx>
     {
@@ -239,7 +240,7 @@
 
             // Collect constraints.
             let result0 =
-                self.lub().relate(&a_with_fresh, &b_with_fresh)?;
+                self.lub(a_is_expected).relate(&a_with_fresh, &b_with_fresh)?;
             let result0 =
                 self.infcx.resolve_type_vars_if_possible(&result0);
             debug!("lub result0 = {:?}", result0);
@@ -311,7 +312,7 @@
         }
     }
 
-    pub fn higher_ranked_glb<T>(&self, a: &Binder<T>, b: &Binder<T>)
+    pub fn higher_ranked_glb<T>(&mut self, a: &Binder<T>, b: &Binder<T>, a_is_expected: bool)
                                 -> RelateResult<'tcx, Binder<T>>
         where T: Relate<'tcx>
     {
@@ -333,7 +334,7 @@
 
             // Collect constraints.
             let result0 =
-                self.glb().relate(&a_with_fresh, &b_with_fresh)?;
+                self.glb(a_is_expected).relate(&a_with_fresh, &b_with_fresh)?;
             let result0 =
                 self.infcx.resolve_type_vars_if_possible(&result0);
             debug!("glb result0 = {:?}", result0);
diff --git a/src/librustc/infer/lattice.rs b/src/librustc/infer/lattice.rs
index 1a2bc4b..eda7842 100644
--- a/src/librustc/infer/lattice.rs
+++ b/src/librustc/infer/lattice.rs
@@ -40,7 +40,7 @@
 
     // Relates the type `v` to `a` and `b` such that `v` represents
     // the LUB/GLB of `a` and `b` as appropriate.
-    fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()>;
+    fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()>;
 }
 
 pub fn super_lattice_tys<'a, 'gcx, 'tcx, L>(this: &mut L,
diff --git a/src/librustc/infer/lub.rs b/src/librustc/infer/lub.rs
index bd46f3a..ad1b32f 100644
--- a/src/librustc/infer/lub.rs
+++ b/src/librustc/infer/lub.rs
@@ -15,29 +15,29 @@
 
 use ty::{self, Ty, TyCtxt};
 use ty::relate::{Relate, RelateResult, TypeRelation};
-use traits::PredicateObligations;
 
 /// "Least upper bound" (common supertype)
-pub struct Lub<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
-    fields: CombineFields<'a, 'gcx, 'tcx>
+pub struct Lub<'combine, 'infcx: 'combine, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
+    fields: &'combine mut CombineFields<'infcx, 'gcx, 'tcx>,
+    a_is_expected: bool,
 }
 
-impl<'a, 'gcx, 'tcx> Lub<'a, 'gcx, 'tcx> {
-    pub fn new(fields: CombineFields<'a, 'gcx, 'tcx>) -> Lub<'a, 'gcx, 'tcx> {
-        Lub { fields: fields }
-    }
-
-    pub fn obligations(self) -> PredicateObligations<'tcx> {
-        self.fields.obligations
+impl<'combine, 'infcx, 'gcx, 'tcx> Lub<'combine, 'infcx, 'gcx, 'tcx> {
+    pub fn new(fields: &'combine mut CombineFields<'infcx, 'gcx, 'tcx>, a_is_expected: bool)
+        -> Lub<'combine, 'infcx, 'gcx, 'tcx>
+    {
+        Lub { fields: fields, a_is_expected: a_is_expected }
     }
 }
 
-impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Lub<'a, 'gcx, 'tcx> {
+impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
+    for Lub<'combine, 'infcx, 'gcx, 'tcx>
+{
     fn tag(&self) -> &'static str { "Lub" }
 
-    fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { self.fields.tcx() }
+    fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() }
 
-    fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
+    fn a_is_expected(&self) -> bool { self.a_is_expected }
 
     fn relate_with_variance<T: Relate<'tcx>>(&mut self,
                                              variance: ty::Variance,
@@ -46,10 +46,10 @@
                                              -> RelateResult<'tcx, T>
     {
         match variance {
-            ty::Invariant => self.fields.equate().relate(a, b),
+            ty::Invariant => self.fields.equate(self.a_is_expected).relate(a, b),
             ty::Covariant => self.relate(a, b),
-            ty::Bivariant => self.fields.bivariate().relate(a, b),
-            ty::Contravariant => self.fields.glb().relate(a, b),
+            ty::Bivariant => self.fields.bivariate(self.a_is_expected).relate(a, b),
+            ty::Contravariant => self.fields.glb(self.a_is_expected).relate(a, b),
         }
     }
 
@@ -71,17 +71,19 @@
                   -> RelateResult<'tcx, ty::Binder<T>>
         where T: Relate<'tcx>
     {
-        self.fields.higher_ranked_lub(a, b)
+        self.fields.higher_ranked_lub(a, b, self.a_is_expected)
     }
 }
 
-impl<'a, 'gcx, 'tcx> LatticeDir<'a, 'gcx, 'tcx> for Lub<'a, 'gcx, 'tcx> {
-    fn infcx(&self) -> &'a InferCtxt<'a, 'gcx, 'tcx> {
+impl<'combine, 'infcx, 'gcx, 'tcx> LatticeDir<'infcx, 'gcx, 'tcx>
+    for Lub<'combine, 'infcx, 'gcx, 'tcx>
+{
+    fn infcx(&self) -> &'infcx InferCtxt<'infcx, 'gcx, 'tcx> {
         self.fields.infcx
     }
 
-    fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
-        let mut sub = self.fields.sub();
+    fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
+        let mut sub = self.fields.sub(self.a_is_expected);
         sub.relate(&a, &v)?;
         sub.relate(&b, &v)?;
         Ok(())
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index 2ea2978..be9adf7 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -32,7 +32,7 @@
 use ty::{TyVid, IntVid, FloatVid};
 use ty::{self, Ty, TyCtxt};
 use ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
-use ty::fold::TypeFoldable;
+use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
 use ty::relate::{Relate, RelateResult, TypeRelation};
 use traits::{self, PredicateObligations, ProjectionMode};
 use rustc_data_structures::unify::{self, UnificationTable};
@@ -48,18 +48,18 @@
 use self::region_inference::{RegionVarBindings, RegionSnapshot};
 use self::unify_key::ToType;
 
-pub mod bivariate;
-pub mod combine;
-pub mod equate;
+mod bivariate;
+mod combine;
+mod equate;
 pub mod error_reporting;
-pub mod glb;
+mod glb;
 mod higher_ranked;
 pub mod lattice;
-pub mod lub;
+mod lub;
 pub mod region_inference;
 pub mod resolve;
 mod freshen;
-pub mod sub;
+mod sub;
 pub mod type_variable;
 pub mod unify_key;
 
@@ -196,12 +196,6 @@
     // FIXME(eddyb) #11161 is the original Expr required?
     ExprAssignable(Span),
 
-    // Relating trait refs when resolving vtables
-    RelateTraitRefs(Span),
-
-    // Relating self types when resolving vtables
-    RelateSelfType(Span),
-
     // Relating trait type parameters to those found in impl etc
     RelateOutputImplTypes(Span),
 
@@ -219,16 +213,26 @@
 
     // `where a == b`
     EquatePredicate(Span),
+
+    // `main` has wrong type
+    MainFunctionType(Span),
+
+    // `start` has wrong type
+    StartFunctionType(Span),
+
+    // intrinsic has wrong type
+    IntrinsicType(Span),
+
+    // method receiver
+    MethodReceiver(Span),
 }
 
 impl TypeOrigin {
-    fn as_str(&self) -> &'static str {
+    fn as_failure_str(&self) -> &'static str {
         match self {
             &TypeOrigin::Misc(_) |
-            &TypeOrigin::RelateSelfType(_) |
             &TypeOrigin::RelateOutputImplTypes(_) |
             &TypeOrigin::ExprAssignable(_) => "mismatched types",
-            &TypeOrigin::RelateTraitRefs(_) => "mismatched traits",
             &TypeOrigin::MethodCompatCheck(_) => "method not compatible with trait",
             &TypeOrigin::MatchExpressionArm(_, _, source) => match source {
                 hir::MatchSource::IfLetDesugar{..} => "`if let` arms have incompatible types",
@@ -238,13 +242,31 @@
             &TypeOrigin::IfExpressionWithNoElse(_) => "if may be missing an else clause",
             &TypeOrigin::RangeExpression(_) => "start and end of range have incompatible types",
             &TypeOrigin::EquatePredicate(_) => "equality predicate not satisfied",
+            &TypeOrigin::MainFunctionType(_) => "main function has wrong type",
+            &TypeOrigin::StartFunctionType(_) => "start function has wrong type",
+            &TypeOrigin::IntrinsicType(_) => "intrinsic has wrong type",
+            &TypeOrigin::MethodReceiver(_) => "mismatched method receiver",
         }
     }
-}
 
-impl fmt::Display for TypeOrigin {
-    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(),fmt::Error> {
-        fmt::Display::fmt(self.as_str(), f)
+    fn as_requirement_str(&self) -> &'static str {
+        match self {
+            &TypeOrigin::Misc(_) => "types are compatible",
+            &TypeOrigin::MethodCompatCheck(_) => "method type is compatible with trait",
+            &TypeOrigin::ExprAssignable(_) => "expression is assignable",
+            &TypeOrigin::RelateOutputImplTypes(_) => {
+                "trait type parameters matches those specified on the impl"
+            }
+            &TypeOrigin::MatchExpressionArm(_, _, _) => "match arms have compatible types",
+            &TypeOrigin::IfExpression(_) => "if and else have compatible types",
+            &TypeOrigin::IfExpressionWithNoElse(_) => "if missing an else returns ()",
+            &TypeOrigin::RangeExpression(_) => "start and end of range have compatible types",
+            &TypeOrigin::EquatePredicate(_) => "equality where clause is satisfied",
+            &TypeOrigin::MainFunctionType(_) => "`main` function has the correct type",
+            &TypeOrigin::StartFunctionType(_) => "`start` function has the correct type",
+            &TypeOrigin::IntrinsicType(_) => "intrinsic has the correct type",
+            &TypeOrigin::MethodReceiver(_) => "method receiver has the correct type",
+        }
     }
 }
 
@@ -799,11 +821,10 @@
         return variables;
     }
 
-    fn combine_fields(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>)
+    fn combine_fields(&'a self, trace: TypeTrace<'tcx>)
                       -> CombineFields<'a, 'gcx, 'tcx> {
         CombineFields {
             infcx: self,
-            a_is_expected: a_is_expected,
             trace: trace,
             cause: None,
             obligations: PredicateObligations::new(),
@@ -814,36 +835,36 @@
         -> InferResult<'tcx, T>
         where T: Relate<'tcx>
     {
-        let mut equate = self.combine_fields(a_is_expected, trace).equate();
-        let result = equate.relate(a, b);
-        result.map(|t| InferOk { value: t, obligations: equate.obligations() })
+        let mut fields = self.combine_fields(trace);
+        let result = fields.equate(a_is_expected).relate(a, b);
+        result.map(move |t| InferOk { value: t, obligations: fields.obligations })
     }
 
     pub fn sub<T>(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>, a: &T, b: &T)
         -> InferResult<'tcx, T>
         where T: Relate<'tcx>
     {
-        let mut sub = self.combine_fields(a_is_expected, trace).sub();
-        let result = sub.relate(a, b);
-        result.map(|t| InferOk { value: t, obligations: sub.obligations() })
+        let mut fields = self.combine_fields(trace);
+        let result = fields.sub(a_is_expected).relate(a, b);
+        result.map(move |t| InferOk { value: t, obligations: fields.obligations })
     }
 
     pub fn lub<T>(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>, a: &T, b: &T)
         -> InferResult<'tcx, T>
         where T: Relate<'tcx>
     {
-        let mut lub = self.combine_fields(a_is_expected, trace).lub();
-        let result = lub.relate(a, b);
-        result.map(|t| InferOk { value: t, obligations: lub.obligations() })
+        let mut fields = self.combine_fields(trace);
+        let result = fields.lub(a_is_expected).relate(a, b);
+        result.map(move |t| InferOk { value: t, obligations: fields.obligations })
     }
 
     pub fn glb<T>(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>, a: &T, b: &T)
         -> InferResult<'tcx, T>
         where T: Relate<'tcx>
     {
-        let mut glb = self.combine_fields(a_is_expected, trace).glb();
-        let result = glb.relate(a, b);
-        result.map(|t| InferOk { value: t, obligations: glb.obligations() })
+        let mut fields = self.combine_fields(trace);
+        let result = fields.glb(a_is_expected).relate(a, b);
+        result.map(move |t| InferOk { value: t, obligations: fields.obligations })
     }
 
     fn start_snapshot(&self) -> CombinedSnapshot {
@@ -1468,104 +1489,50 @@
     // error type, meaning that an error occurred when typechecking this expression),
     // this is a derived error. The error cascaded from another error (that was already
     // reported), so it's not useful to display it to the user.
-    // The following four methods -- type_error_message_str, type_error_message_str_with_expected,
-    // type_error_message, and report_mismatched_types -- implement this logic.
+    // The following methods implement this logic.
     // They check if either the actual or expected type is TyError, and don't print the error
     // in this case. The typechecker should only ever report type errors involving mismatched
-    // types using one of these four methods, and should not call span_err directly for such
+    // types using one of these methods, and should not call span_err directly for such
     // errors.
-    pub fn type_error_message_str<M>(&self,
-                                     sp: Span,
-                                     mk_msg: M,
-                                     actual_ty: String,
-                                     err: Option<&TypeError<'tcx>>)
-        where M: FnOnce(Option<String>, String) -> String,
-    {
-        self.type_error_message_str_with_expected(sp, mk_msg, None, actual_ty, err)
-    }
-
-    pub fn type_error_struct_str<M>(&self,
-                                    sp: Span,
-                                    mk_msg: M,
-                                    actual_ty: String,
-                                    err: Option<&TypeError<'tcx>>)
-                                    -> DiagnosticBuilder<'tcx>
-        where M: FnOnce(Option<String>, String) -> String,
-    {
-        self.type_error_struct_str_with_expected(sp, mk_msg, None, actual_ty, err)
-    }
-
-    pub fn type_error_message_str_with_expected<M>(&self,
-                                                   sp: Span,
-                                                   mk_msg: M,
-                                                   expected_ty: Option<Ty<'tcx>>,
-                                                   actual_ty: String,
-                                                   err: Option<&TypeError<'tcx>>)
-        where M: FnOnce(Option<String>, String) -> String,
-    {
-        self.type_error_struct_str_with_expected(sp, mk_msg, expected_ty, actual_ty, err)
-            .emit();
-    }
-
-    pub fn type_error_struct_str_with_expected<M>(&self,
-                                                  sp: Span,
-                                                  mk_msg: M,
-                                                  expected_ty: Option<Ty<'tcx>>,
-                                                  actual_ty: String,
-                                                  err: Option<&TypeError<'tcx>>)
-                                                  -> DiagnosticBuilder<'tcx>
-        where M: FnOnce(Option<String>, String) -> String,
-    {
-        debug!("hi! expected_ty = {:?}, actual_ty = {}", expected_ty, actual_ty);
-
-        let resolved_expected = expected_ty.map(|e_ty| self.resolve_type_vars_if_possible(&e_ty));
-
-        if !resolved_expected.references_error() {
-            let error_str = err.map_or("".to_string(), |t_err| {
-                format!(" ({})", t_err)
-            });
-
-            let mut db = self.tcx.sess.struct_span_err(sp, &format!("{}{}",
-                mk_msg(resolved_expected.map(|t| self.ty_to_string(t)), actual_ty),
-                error_str));
-
-            if let Some(err) = err {
-                self.tcx.note_and_explain_type_err(&mut db, err, sp);
-            }
-            db
-        } else {
-            self.tcx.sess.diagnostic().struct_dummy()
-        }
-    }
 
     pub fn type_error_message<M>(&self,
                                  sp: Span,
                                  mk_msg: M,
-                                 actual_ty: Ty<'tcx>,
-                                 err: Option<&TypeError<'tcx>>)
+                                 actual_ty: Ty<'tcx>)
         where M: FnOnce(String) -> String,
     {
-        self.type_error_struct(sp, mk_msg, actual_ty, err).emit();
+        self.type_error_struct(sp, mk_msg, actual_ty).emit();
     }
 
+    // FIXME: this results in errors without an error code. Deprecate?
     pub fn type_error_struct<M>(&self,
                                 sp: Span,
                                 mk_msg: M,
-                                actual_ty: Ty<'tcx>,
-                                err: Option<&TypeError<'tcx>>)
+                                actual_ty: Ty<'tcx>)
                                 -> DiagnosticBuilder<'tcx>
         where M: FnOnce(String) -> String,
     {
+        self.type_error_struct_with_diag(sp, |actual_ty| {
+            self.tcx.sess.struct_span_err(sp, &mk_msg(actual_ty))
+        }, actual_ty)
+    }
+
+    pub fn type_error_struct_with_diag<M>(&self,
+                                          sp: Span,
+                                          mk_diag: M,
+                                          actual_ty: Ty<'tcx>)
+                                          -> DiagnosticBuilder<'tcx>
+        where M: FnOnce(String) -> DiagnosticBuilder<'tcx>,
+    {
         let actual_ty = self.resolve_type_vars_if_possible(&actual_ty);
+        debug!("type_error_struct_with_diag({:?}, {:?})", sp, actual_ty);
 
         // Don't report an error if actual type is TyError.
         if actual_ty.references_error() {
             return self.tcx.sess.diagnostic().struct_dummy();
         }
 
-        self.type_error_struct_str(sp,
-            move |_e, a| { mk_msg(a) },
-            self.ty_to_string(actual_ty), err)
+        mk_diag(self.ty_to_string(actual_ty))
     }
 
     pub fn report_mismatched_types(&self,
@@ -1646,8 +1613,8 @@
         };
 
         let match_pair = match_a.map_bound(|p| (p.projection_ty.trait_ref, p.ty));
-        let combine = self.combine_fields(true, trace);
-        let result = combine.higher_ranked_match(span, &match_pair, &match_b)?;
+        let mut combine = self.combine_fields(trace);
+        let result = combine.higher_ranked_match(span, &match_pair, &match_b, true)?;
         Ok(InferOk { value: result, obligations: combine.obligations })
     }
 
@@ -1833,14 +1800,16 @@
             TypeOrigin::MethodCompatCheck(span) => span,
             TypeOrigin::ExprAssignable(span) => span,
             TypeOrigin::Misc(span) => span,
-            TypeOrigin::RelateTraitRefs(span) => span,
-            TypeOrigin::RelateSelfType(span) => span,
             TypeOrigin::RelateOutputImplTypes(span) => span,
             TypeOrigin::MatchExpressionArm(match_span, _, _) => match_span,
             TypeOrigin::IfExpression(span) => span,
             TypeOrigin::IfExpressionWithNoElse(span) => span,
             TypeOrigin::RangeExpression(span) => span,
             TypeOrigin::EquatePredicate(span) => span,
+            TypeOrigin::MainFunctionType(span) => span,
+            TypeOrigin::StartFunctionType(span) => span,
+            TypeOrigin::IntrinsicType(span) => span,
+            TypeOrigin::MethodReceiver(span) => span,
         }
     }
 }
@@ -1891,3 +1860,50 @@
         }
     }
 }
+
+impl<'tcx> TypeFoldable<'tcx> for TypeOrigin {
+    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, _folder: &mut F) -> Self {
+        self.clone()
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> bool {
+        false
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for ValuePairs<'tcx> {
+    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
+        match *self {
+            ValuePairs::Types(ref ef) => {
+                ValuePairs::Types(ef.fold_with(folder))
+            }
+            ValuePairs::TraitRefs(ref ef) => {
+                ValuePairs::TraitRefs(ef.fold_with(folder))
+            }
+            ValuePairs::PolyTraitRefs(ref ef) => {
+                ValuePairs::PolyTraitRefs(ef.fold_with(folder))
+            }
+        }
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        match *self {
+            ValuePairs::Types(ref ef) => ef.visit_with(visitor),
+            ValuePairs::TraitRefs(ref ef) => ef.visit_with(visitor),
+            ValuePairs::PolyTraitRefs(ref ef) => ef.visit_with(visitor),
+        }
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for TypeTrace<'tcx> {
+    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
+        TypeTrace {
+            origin: self.origin.fold_with(folder),
+            values: self.values.fold_with(folder)
+        }
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        self.origin.visit_with(visitor) || self.values.visit_with(visitor)
+    }
+}
diff --git a/src/librustc/infer/sub.rs b/src/librustc/infer/sub.rs
index 680dd0d..2f7f525 100644
--- a/src/librustc/infer/sub.rs
+++ b/src/librustc/infer/sub.rs
@@ -15,28 +15,35 @@
 use ty::{self, Ty, TyCtxt};
 use ty::TyVar;
 use ty::relate::{Cause, Relate, RelateResult, TypeRelation};
-use traits::PredicateObligations;
 use std::mem;
 
 /// Ensures `a` is made a subtype of `b`. Returns `a` on success.
-pub struct Sub<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
-    fields: CombineFields<'a, 'gcx, 'tcx>,
+pub struct Sub<'combine, 'infcx: 'combine, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
+    fields: &'combine mut CombineFields<'infcx, 'gcx, 'tcx>,
+    a_is_expected: bool,
 }
 
-impl<'a, 'gcx, 'tcx> Sub<'a, 'gcx, 'tcx> {
-    pub fn new(f: CombineFields<'a, 'gcx, 'tcx>) -> Sub<'a, 'gcx, 'tcx> {
-        Sub { fields: f }
+impl<'combine, 'infcx, 'gcx, 'tcx> Sub<'combine, 'infcx, 'gcx, 'tcx> {
+    pub fn new(f: &'combine mut CombineFields<'infcx, 'gcx, 'tcx>, a_is_expected: bool)
+        -> Sub<'combine, 'infcx, 'gcx, 'tcx>
+    {
+        Sub { fields: f, a_is_expected: a_is_expected }
     }
 
-    pub fn obligations(self) -> PredicateObligations<'tcx> {
-        self.fields.obligations
+    fn with_expected_switched<R, F: FnOnce(&mut Self) -> R>(&mut self, f: F) -> R {
+        self.a_is_expected = !self.a_is_expected;
+        let result = f(self);
+        self.a_is_expected = !self.a_is_expected;
+        result
     }
 }
 
-impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Sub<'a, 'gcx, 'tcx> {
+impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
+    for Sub<'combine, 'infcx, 'gcx, 'tcx>
+{
     fn tag(&self) -> &'static str { "Sub" }
-    fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { self.fields.infcx.tcx }
-    fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
+    fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.infcx.tcx }
+    fn a_is_expected(&self) -> bool { self.a_is_expected }
 
     fn with_cause<F,R>(&mut self, cause: Cause, f: F) -> R
         where F: FnOnce(&mut Self) -> R
@@ -56,10 +63,10 @@
                                              -> RelateResult<'tcx, T>
     {
         match variance {
-            ty::Invariant => self.fields.equate().relate(a, b),
+            ty::Invariant => self.fields.equate(self.a_is_expected).relate(a, b),
             ty::Covariant => self.relate(a, b),
-            ty::Bivariant => self.fields.bivariate().relate(a, b),
-            ty::Contravariant => self.fields.switch_expected().sub().relate(b, a),
+            ty::Bivariant => self.fields.bivariate(self.a_is_expected).relate(a, b),
+            ty::Contravariant => self.with_expected_switched(|this| { this.relate(b, a) }),
         }
     }
 
@@ -80,12 +87,11 @@
             }
             (&ty::TyInfer(TyVar(a_id)), _) => {
                 self.fields
-                    .switch_expected()
-                    .instantiate(b, SupertypeOf, a_id)?;
+                    .instantiate(b, SupertypeOf, a_id, !self.a_is_expected)?;
                 Ok(a)
             }
             (_, &ty::TyInfer(TyVar(b_id))) => {
-                self.fields.instantiate(a, SubtypeOf, b_id)?;
+                self.fields.instantiate(a, SubtypeOf, b_id, self.a_is_expected)?;
                 Ok(a)
             }
 
@@ -116,6 +122,6 @@
                   -> RelateResult<'tcx, ty::Binder<T>>
         where T: Relate<'tcx>
     {
-        self.fields.higher_ranked_sub(a, b)
+        self.fields.higher_ranked_sub(a, b, self.a_is_expected)
     }
 }
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index ce3d72d..daac315 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -29,7 +29,7 @@
 use middle::privacy::AccessLevels;
 use ty::TyCtxt;
 use session::{config, early_error, Session};
-use lint::{Level, LevelSource, Lint, LintId, LintPass};
+use lint::{Level, LevelSource, Lint, LintId, LintPass, LintSource};
 use lint::{EarlyLintPassObject, LateLintPassObject};
 use lint::{Default, CommandLine, Node, Allow, Warn, Deny, Forbid};
 use lint::builtin;
@@ -45,7 +45,6 @@
 use errors::DiagnosticBuilder;
 use hir;
 use hir::intravisit as hir_visit;
-use hir::intravisit::{IdVisitor, IdVisitingOperation};
 use syntax::visit as ast_visit;
 
 /// Information about the registered lints.
@@ -366,18 +365,18 @@
     attr::mark_used(attr);
 
     let meta = &attr.node.value;
-    let metas = match meta.node {
-        ast::MetaItemKind::List(_, ref metas) => metas,
-        _ => {
-            out.push(Err(meta.span));
-            return out;
-        }
+    let metas = if let Some(metas) = meta.meta_item_list() {
+        metas
+    } else {
+        out.push(Err(meta.span));
+        return out;
     };
 
     for meta in metas {
-        out.push(match meta.node {
-            ast::MetaItemKind::Word(ref lint_name) => Ok((lint_name.clone(), level, meta.span)),
-            _ => Err(meta.span),
+        out.push(if meta.is_word() {
+            Ok((meta.name().clone(), level, meta.span))
+        } else {
+            Err(meta.span)
         });
     }
 
@@ -600,13 +599,23 @@
             };
 
             for (lint_id, level, span) in v {
-                let now = self.lints().get_level_source(lint_id).0;
+                let (now, now_source) = self.lints().get_level_source(lint_id);
                 if now == Forbid && level != Forbid {
                     let lint_name = lint_id.as_str();
-                    span_err!(self.sess(), span, E0453,
-                              "{}({}) overruled by outer forbid({})",
-                              level.as_str(), lint_name,
-                              lint_name);
+                    let mut diag_builder = struct_span_err!(self.sess(), span, E0453,
+                                                            "{}({}) overruled by outer forbid({})",
+                                                            level.as_str(), lint_name,
+                                                            lint_name);
+                    match now_source {
+                        LintSource::Default => &mut diag_builder,
+                        LintSource::Node(forbid_source_span) => {
+                            diag_builder.span_note(forbid_source_span,
+                                                   "`forbid` lint level set here")
+                        },
+                        LintSource::CommandLine => {
+                            diag_builder.note("`forbid` lint level was set on command line")
+                        }
+                    }.emit()
                 } else if now != level {
                     let src = self.lints().get_level_source(lint_id).1;
                     self.level_stack().push((lint_id, (now, src)));
@@ -663,9 +672,11 @@
     }
 
     fn visit_ids<F>(&mut self, f: F)
-        where F: FnOnce(&mut IdVisitor<LateContext>)
+        where F: FnOnce(&mut IdVisitor)
     {
-        let mut v = IdVisitor::new(self);
+        let mut v = IdVisitor {
+            cx: self
+        };
         f(&mut v);
     }
 }
@@ -779,7 +790,7 @@
     fn visit_fn(&mut self, fk: hir_visit::FnKind<'v>, decl: &'v hir::FnDecl,
                 body: &'v hir::Block, span: Span, id: ast::NodeId) {
         run_lints!(self, check_fn, late_passes, fk, decl, body, span, id);
-        hir_visit::walk_fn(self, fk, decl, body, span);
+        hir_visit::walk_fn(self, fk, decl, body, span, id);
         run_lints!(self, check_fn_post, late_passes, fk, decl, body, span, id);
     }
 
@@ -820,7 +831,7 @@
 
     fn visit_mod(&mut self, m: &hir::Mod, s: Span, n: ast::NodeId) {
         run_lints!(self, check_mod, late_passes, m, s, n);
-        hir_visit::walk_mod(self, m);
+        hir_visit::walk_mod(self, m, n);
         run_lints!(self, check_mod_post, late_passes, m, s, n);
     }
 
@@ -859,7 +870,7 @@
     fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) {
         self.with_lint_attrs(&trait_item.attrs, |cx| {
             run_lints!(cx, check_trait_item, late_passes, trait_item);
-            cx.visit_ids(|v| v.visit_trait_item(trait_item));
+            cx.visit_ids(|v| hir_visit::walk_trait_item(v, trait_item));
             hir_visit::walk_trait_item(cx, trait_item);
             run_lints!(cx, check_trait_item_post, late_passes, trait_item);
         });
@@ -868,7 +879,7 @@
     fn visit_impl_item(&mut self, impl_item: &hir::ImplItem) {
         self.with_lint_attrs(&impl_item.attrs, |cx| {
             run_lints!(cx, check_impl_item, late_passes, impl_item);
-            cx.visit_ids(|v| v.visit_impl_item(impl_item));
+            cx.visit_ids(|v| hir_visit::walk_impl_item(v, impl_item));
             hir_visit::walk_impl_item(cx, impl_item);
             run_lints!(cx, check_impl_item_post, late_passes, impl_item);
         });
@@ -1046,16 +1057,30 @@
     }
 }
 
+struct IdVisitor<'a, 'b: 'a, 'tcx: 'a+'b> {
+    cx: &'a mut LateContext<'b, 'tcx>
+}
+
 // Output any lints that were previously added to the session.
-impl<'a, 'tcx> IdVisitingOperation for LateContext<'a, 'tcx> {
+impl<'a, 'b, 'tcx, 'v> hir_visit::Visitor<'v> for IdVisitor<'a, 'b, 'tcx> {
+
     fn visit_id(&mut self, id: ast::NodeId) {
-        if let Some(lints) = self.sess().lints.borrow_mut().remove(&id) {
+        if let Some(lints) = self.cx.sess().lints.borrow_mut().remove(&id) {
             debug!("LateContext::visit_id: id={:?} lints={:?}", id, lints);
             for (lint_id, span, msg) in lints {
-                self.span_lint(lint_id.lint, span, &msg[..])
+                self.cx.span_lint(lint_id.lint, span, &msg[..])
             }
         }
     }
+
+    fn visit_trait_item(&mut self, _ti: &hir::TraitItem) {
+        // Do not recurse into trait or impl items automatically. These are
+        // processed separately by calling hir_visit::walk_trait_item()
+    }
+
+    fn visit_impl_item(&mut self, _ii: &hir::ImplItem) {
+        // See visit_trait_item()
+    }
 }
 
 enum CheckLintNameResult {
@@ -1172,7 +1197,6 @@
 
     // Visit the whole crate.
     cx.with_lint_attrs(&krate.attrs, |cx| {
-        cx.visit_id(ast::CRATE_NODE_ID);
         cx.visit_ids(|v| {
             hir_visit::walk_crate(v, krate);
         });
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index fd9463b..32344a7 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -44,7 +44,7 @@
 use syntax_pos::Span;
 use rustc_back::target::Target;
 use hir;
-use hir::intravisit::{IdVisitor, IdVisitingOperation, Visitor};
+use hir::intravisit::Visitor;
 
 pub use self::DefLike::{DlDef, DlField, DlImpl};
 pub use self::NativeLibraryKind::{NativeStatic, NativeFramework, NativeUnknown};
@@ -120,12 +120,6 @@
     pub vis: ty::Visibility,
 }
 
-pub enum FoundAst<'ast> {
-    Found(&'ast InlinedItem),
-    FoundParent(DefId, &'ast hir::Item),
-    NotFound,
-}
-
 #[derive(Copy, Clone, Debug)]
 pub struct ExternCrate {
     /// def_id of an `extern crate` in the current crate that caused
@@ -250,7 +244,10 @@
 
     // misc. metadata
     fn maybe_get_item_ast<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-                              -> FoundAst<'tcx>;
+                              -> Option<(&'tcx InlinedItem, ast::NodeId)>;
+    fn local_node_for_inlined_defid(&'tcx self, def_id: DefId) -> Option<ast::NodeId>;
+    fn defid_for_inlined_node(&'tcx self, node_id: ast::NodeId) -> Option<DefId>;
+
     fn maybe_get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                               -> Option<Mir<'tcx>>;
     fn is_item_mir_available(&self, def: DefId) -> bool;
@@ -292,11 +289,6 @@
             InlinedItem::ImplItem(_, ref ii) => visitor.visit_impl_item(ii),
         }
     }
-
-    pub fn visit_ids<O: IdVisitingOperation>(&self, operation: &mut O) {
-        let mut id_visitor = IdVisitor::new(operation);
-        self.visit(&mut id_visitor);
-    }
 }
 
 // FIXME: find a better place for this?
@@ -452,7 +444,16 @@
 
     // misc. metadata
     fn maybe_get_item_ast<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-                              -> FoundAst<'tcx> { bug!("maybe_get_item_ast") }
+                              -> Option<(&'tcx InlinedItem, ast::NodeId)> {
+        bug!("maybe_get_item_ast")
+    }
+    fn local_node_for_inlined_defid(&'tcx self, def_id: DefId) -> Option<ast::NodeId> {
+        bug!("local_node_for_inlined_defid")
+    }
+    fn defid_for_inlined_node(&'tcx self, node_id: ast::NodeId) -> Option<DefId> {
+        bug!("defid_for_inlined_node")
+    }
+
     fn maybe_get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                               -> Option<Mir<'tcx>> { bug!("maybe_get_item_mir") }
     fn is_item_mir_available(&self, def: DefId) -> bool {
diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs
index 6fe9811..446767e 100644
--- a/src/librustc/middle/effect.rs
+++ b/src/librustc/middle/effect.rs
@@ -79,7 +79,7 @@
 
 impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
     fn visit_fn(&mut self, fn_kind: FnKind<'v>, fn_decl: &'v hir::FnDecl,
-                block: &'v hir::Block, span: Span, _: ast::NodeId) {
+                block: &'v hir::Block, span: Span, id: ast::NodeId) {
 
         let (is_item_fn, is_unsafe_fn) = match fn_kind {
             FnKind::ItemFn(_, _, unsafety, _, _, _, _) =>
@@ -96,7 +96,7 @@
             self.unsafe_context = UnsafeContext::new(SafeContext)
         }
 
-        intravisit::walk_fn(self, fn_kind, fn_decl, block, span);
+        intravisit::walk_fn(self, fn_kind, fn_decl, block, span, id);
 
         self.unsafe_context = old_unsafe_context
     }
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index 6551e01..18b80a9 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -271,10 +271,19 @@
 
 impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
     pub fn new(delegate: &'a mut (Delegate<'tcx>+'a),
-               infcx: &'a InferCtxt<'a, 'gcx, 'tcx>) -> Self
+               infcx: &'a InferCtxt<'a, 'gcx, 'tcx>)
+               -> Self
+    {
+        ExprUseVisitor::with_options(delegate, infcx, mc::MemCategorizationOptions::default())
+    }
+
+    pub fn with_options(delegate: &'a mut (Delegate<'tcx>+'a),
+                        infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
+                        options: mc::MemCategorizationOptions)
+               -> Self
     {
         ExprUseVisitor {
-            mc: mc::MemCategorizationContext::new(infcx),
+            mc: mc::MemCategorizationContext::with_options(infcx, options),
             delegate: delegate
         }
     }
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index 960305e..a209b1d 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -359,7 +359,6 @@
     StartFnLangItem,                 "start",                   start_fn;
 
     EhPersonalityLangItem,           "eh_personality",          eh_personality;
-    EhPersonalityCatchLangItem,      "eh_personality_catch",    eh_personality_catch;
     EhUnwindResumeLangItem,          "eh_unwind_resume",        eh_unwind_resume;
     MSVCTryFilterLangItem,           "msvc_try_filter",         msvc_try_filter;
 
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index ea3765c..1222b5f 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -390,7 +390,7 @@
 
     // gather up the various local variables, significant expressions,
     // and so forth:
-    intravisit::walk_fn(&mut fn_maps, fk, decl, body, sp);
+    intravisit::walk_fn(&mut fn_maps, fk, decl, body, sp, id);
 
     // Special nodes and variables:
     // - exit_ln represents the end of the fn, either by return or panic
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 28bfb46..0bc3c1a 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -259,6 +259,18 @@
 #[derive(Copy, Clone)]
 pub struct MemCategorizationContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     pub infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
+    options: MemCategorizationOptions,
+}
+
+#[derive(Copy, Clone, Default)]
+pub struct MemCategorizationOptions {
+    // If true, then when analyzing a closure upvar, if the closure
+    // has a missing kind, we treat it like a Fn closure. When false,
+    // we ICE if the closure has a missing kind. Should be false
+    // except during closure kind inference. It is used by the
+    // mem-categorization code to be able to have stricter assertions
+    // (which are always true except during upvar inference).
+    pub during_closure_kind_inference: bool,
 }
 
 pub type McResult<T> = Result<T, ()>;
@@ -362,7 +374,16 @@
 impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
     pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>)
                -> MemCategorizationContext<'a, 'gcx, 'tcx> {
-        MemCategorizationContext { infcx: infcx }
+        MemCategorizationContext::with_options(infcx, MemCategorizationOptions::default())
+    }
+
+    pub fn with_options(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
+                        options: MemCategorizationOptions)
+                        -> MemCategorizationContext<'a, 'gcx, 'tcx> {
+        MemCategorizationContext {
+            infcx: infcx,
+            options: options,
+        }
     }
 
     fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {
@@ -584,10 +605,20 @@
                               self.cat_upvar(id, span, var_id, fn_node_id, kind)
                           }
                           None => {
-                              span_bug!(
-                                  span,
-                                  "No closure kind for {:?}",
-                                  closure_id);
+                              if !self.options.during_closure_kind_inference {
+                                  span_bug!(
+                                      span,
+                                      "No closure kind for {:?}",
+                                      closure_id);
+                              }
+
+                              // during closure kind inference, we
+                              // don't know the closure kind yet, but
+                              // it's ok because we detect that we are
+                              // accessing an upvar and handle that
+                              // case specially anyhow. Use Fn
+                              // arbitrarily.
+                              self.cat_upvar(id, span, var_id, fn_node_id, ty::ClosureKind::Fn)
                           }
                       }
                   }
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index a0c2416..6ed91cd 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -30,7 +30,7 @@
 use syntax::parse::token::InternedString;
 use syntax::feature_gate::UnstableFeatures;
 
-use errors::{ColorConfig, Handler};
+use errors::{ColorConfig, FatalError, Handler};
 
 use getopts;
 use std::collections::HashMap;
@@ -61,7 +61,7 @@
     FullDebugInfo,
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, Hash)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
 pub enum OutputType {
     Bitcode,
     Assembly,
@@ -105,6 +105,17 @@
             OutputType::DepInfo => "dep-info",
         }
     }
+
+    pub fn extension(&self) -> &'static str {
+        match *self {
+            OutputType::Bitcode => "bc",
+            OutputType::Assembly => "s",
+            OutputType::LlvmAssembly => "ll",
+            OutputType::Object => "o",
+            OutputType::DepInfo => "d",
+            OutputType::Exe => "",
+        }
+    }
 }
 
 #[derive(Clone)]
@@ -215,15 +226,7 @@
                      flavor: OutputType,
                      codegen_unit_name: Option<&str>)
                      -> PathBuf {
-        let extension = match flavor {
-            OutputType::Bitcode => "bc",
-            OutputType::Assembly => "s",
-            OutputType::LlvmAssembly => "ll",
-            OutputType::Object => "o",
-            OutputType::DepInfo => "d",
-            OutputType::Exe => "",
-        };
-
+        let extension = flavor.extension();
         self.temp_path_ext(extension, codegen_unit_name)
     }
 
@@ -327,6 +330,11 @@
             self.debugging_opts.dump_dep_graph ||
             self.debugging_opts.query_dep_graph
     }
+
+    pub fn single_codegen_unit(&self) -> bool {
+        self.incremental.is_none() ||
+        self.cg.codegen_units == 1
+    }
 }
 
 // The type of entry function, so
@@ -455,6 +463,8 @@
         pub const parse_bool: Option<&'static str> = None;
         pub const parse_opt_bool: Option<&'static str> =
             Some("one of: `y`, `yes`, `on`, `n`, `no`, or `off`");
+        pub const parse_all_bool: Option<&'static str> =
+            Some("one of: `y`, `yes`, `on`, `n`, `no`, or `off`");
         pub const parse_string: Option<&'static str> = Some("a string");
         pub const parse_opt_string: Option<&'static str> = Some("a string");
         pub const parse_list: Option<&'static str> = Some("a space-separated list of strings");
@@ -504,6 +514,25 @@
             }
         }
 
+        fn parse_all_bool(slot: &mut bool, v: Option<&str>) -> bool {
+            match v {
+                Some(s) => {
+                    match s {
+                        "n" | "no" | "off" => {
+                            *slot = false;
+                        }
+                        "y" | "yes" | "on" => {
+                            *slot = true;
+                        }
+                        _ => { return false; }
+                    }
+
+                    true
+                },
+                None => { *slot = true; true }
+            }
+        }
+
         fn parse_opt_string(slot: &mut Option<String>, v: Option<&str>) -> bool {
             match v {
                 Some(s) => { *slot = Some(s.to_string()); true },
@@ -652,7 +681,6 @@
         "panic strategy to compile crate with"),
 }
 
-
 options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
          build_debugging_options, "Z", "debugging",
          DB_OPTIONS, db_type_desc, dbsetters,
@@ -749,7 +777,7 @@
           "dump MIR state at various points in translation"),
     dump_mir_dir: Option<String> = (None, parse_opt_string,
           "the directory the MIR is dumped into"),
-    orbit: bool = (false, parse_bool,
+    orbit: bool = (true, parse_all_bool,
           "get MIR where it belongs - everywhere; most importantly, in orbit"),
 }
 
@@ -833,7 +861,10 @@
     let target = match Target::search(&opts.target_triple) {
         Ok(t) => t,
         Err(e) => {
-            panic!(sp.fatal(&format!("Error loading target specification: {}", e)));
+            sp.struct_fatal(&format!("Error loading target specification: {}", e))
+                .help("Use `--print target-list` for a list of built-in targets")
+                .emit();
+            panic!(FatalError);
         }
     };
 
@@ -1137,7 +1168,15 @@
         })
     });
 
-    let debugging_opts = build_debugging_options(matches, error_format);
+    let mut debugging_opts = build_debugging_options(matches, error_format);
+
+    // Incremental compilation only works reliably when translation is done via
+    // MIR, so let's enable -Z orbit if necessary (see #34973).
+    if debugging_opts.incremental.is_some() && !debugging_opts.orbit {
+        early_warn(error_format, "Automatically enabling `-Z orbit` because \
+                                  `-Z incremental` was specified");
+        debugging_opts.orbit = true;
+    }
 
     let parse_only = debugging_opts.parse_only;
     let no_trans = debugging_opts.no_trans;
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index fa9bc7c..cee1823 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -80,7 +80,7 @@
     // forms a unique global identifier for the crate. It is used to allow
     // multiple crates with the same name to coexist. See the
     // trans::back::symbol_names module for more information.
-    pub crate_disambiguator: Cell<ast::Name>,
+    pub crate_disambiguator: RefCell<token::InternedString>,
     pub features: RefCell<feature_gate::Features>,
 
     /// The maximum recursion limit for potentially infinitely recursive
@@ -106,6 +106,9 @@
 }
 
 impl Session {
+    pub fn local_crate_disambiguator(&self) -> token::InternedString {
+        self.crate_disambiguator.borrow().clone()
+    }
     pub fn struct_span_warn<'a, S: Into<MultiSpan>>(&'a self,
                                                     sp: S,
                                                     msg: &str)
@@ -126,20 +129,14 @@
                                                    sp: S,
                                                    msg: &str)
                                                    -> DiagnosticBuilder<'a>  {
-        match split_msg_into_multilines(msg) {
-            Some(ref msg) => self.diagnostic().struct_span_err(sp, msg),
-            None => self.diagnostic().struct_span_err(sp, msg),
-        }
+        self.diagnostic().struct_span_err(sp, msg)
     }
     pub fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self,
                                                              sp: S,
                                                              msg: &str,
                                                              code: &str)
                                                              -> DiagnosticBuilder<'a>  {
-        match split_msg_into_multilines(msg) {
-            Some(ref msg) => self.diagnostic().struct_span_err_with_code(sp, msg, code),
-            None => self.diagnostic().struct_span_err_with_code(sp, msg, code),
-        }
+        self.diagnostic().struct_span_err_with_code(sp, msg, code)
     }
     pub fn struct_err<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a>  {
         self.diagnostic().struct_err(msg)
@@ -178,16 +175,10 @@
         }
     }
     pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
-        match split_msg_into_multilines(msg) {
-            Some(msg) => self.diagnostic().span_err(sp, &msg),
-            None => self.diagnostic().span_err(sp, msg)
-        }
+        self.diagnostic().span_err(sp, msg)
     }
     pub fn span_err_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: &str) {
-        match split_msg_into_multilines(msg) {
-            Some(msg) => self.diagnostic().span_err_with_code(sp, &msg, code),
-            None => self.diagnostic().span_err_with_code(sp, msg, code)
-        }
+        self.diagnostic().span_err_with_code(sp, &msg, code)
     }
     pub fn err(&self, msg: &str) {
         self.diagnostic().err(msg)
@@ -343,67 +334,6 @@
     }
 }
 
-fn split_msg_into_multilines(msg: &str) -> Option<String> {
-    // Conditions for enabling multi-line errors:
-    if !msg.contains("mismatched types") &&
-        !msg.contains("type mismatch resolving") &&
-        !msg.contains("if and else have incompatible types") &&
-        !msg.contains("if may be missing an else clause") &&
-        !msg.contains("match arms have incompatible types") &&
-        !msg.contains("structure constructor specifies a structure of type") &&
-        !msg.contains("has an incompatible type for trait") {
-            return None
-    }
-    let first = msg.match_indices("expected").filter(|s| {
-        let last = msg[..s.0].chars().rev().next();
-        last == Some(' ') || last == Some('(')
-    }).map(|(a, b)| (a - 1, a + b.len()));
-    let second = msg.match_indices("found").filter(|s| {
-        msg[..s.0].chars().rev().next() == Some(' ')
-    }).map(|(a, b)| (a - 1, a + b.len()));
-
-    let mut new_msg = String::new();
-    let mut head = 0;
-
-    // Insert `\n` before expected and found.
-    for (pos1, pos2) in first.zip(second) {
-        new_msg = new_msg +
-        // A `(` may be preceded by a space and it should be trimmed
-                  msg[head..pos1.0].trim_right() + // prefix
-                  "\n" +                           // insert before first
-                  &msg[pos1.0..pos1.1] +           // insert what first matched
-                  &msg[pos1.1..pos2.0] +           // between matches
-                  "\n   " +                        // insert before second
-        //           123
-        // `expected` is 3 char longer than `found`. To align the types,
-        // `found` gets 3 spaces prepended.
-                  &msg[pos2.0..pos2.1];            // insert what second matched
-
-        head = pos2.1;
-    }
-
-    let mut tail = &msg[head..];
-    let third = tail.find("(values differ")
-                   .or(tail.find("(lifetime"))
-                   .or(tail.find("(cyclic type of infinite size"));
-    // Insert `\n` before any remaining messages which match.
-    if let Some(pos) = third {
-        // The end of the message may just be wrapped in `()` without
-        // `expected`/`found`.  Push this also to a new line and add the
-        // final tail after.
-        new_msg = new_msg +
-        // `(` is usually preceded by a space and should be trimmed.
-                  tail[..pos].trim_right() + // prefix
-                  "\n" +                     // insert before paren
-                  &tail[pos..];              // append the tail
-
-        tail = "";
-    }
-
-    new_msg.push_str(tail);
-    return Some(new_msg);
-}
-
 pub fn build_session(sopts: config::Options,
                      dep_graph: &DepGraph,
                      local_crate_source_file: Option<PathBuf>,
@@ -511,7 +441,7 @@
         plugin_attributes: RefCell::new(Vec::new()),
         crate_types: RefCell::new(Vec::new()),
         dependency_formats: RefCell::new(FnvHashMap()),
-        crate_disambiguator: Cell::new(token::intern("")),
+        crate_disambiguator: RefCell::new(token::intern("").as_str()),
         features: RefCell::new(feature_gate::Features::new()),
         recursion_limit: Cell::new(64),
         next_node_id: Cell::new(1),
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index 3b9ecb8..67ad887 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -26,8 +26,9 @@
 
 use fmt_macros::{Parser, Piece, Position};
 use hir::def_id::DefId;
-use infer::{InferCtxt};
+use infer::{self, InferCtxt, TypeOrigin};
 use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
+use ty::error::ExpectedFound;
 use ty::fast_reject;
 use ty::fold::TypeFolder;
 use ty::subst::{self, Subst, TypeSpace};
@@ -107,24 +108,63 @@
         let predicate =
             self.resolve_type_vars_if_possible(&obligation.predicate);
 
-        if !predicate.references_error() {
-            if let Some(warning_node_id) = warning_node_id {
-                self.tcx.sess.add_lint(
-                    ::lint::builtin::UNSIZED_IN_TUPLE,
-                    warning_node_id,
-                    obligation.cause.span,
-                    format!("type mismatch resolving `{}`: {}",
-                            predicate,
-                            error.err));
-            } else {
-                let mut err = struct_span_err!(self.tcx.sess, obligation.cause.span, E0271,
-                                               "type mismatch resolving `{}`: {}",
-                                               predicate,
-                                               error.err);
-                self.note_obligation_cause(&mut err, obligation);
-                err.emit();
-            }
+        if predicate.references_error() {
+            return
         }
+        if let Some(warning_node_id) = warning_node_id {
+            self.tcx.sess.add_lint(
+                ::lint::builtin::UNSIZED_IN_TUPLE,
+                warning_node_id,
+                obligation.cause.span,
+                format!("type mismatch resolving `{}`: {}",
+                        predicate,
+                        error.err));
+            return
+        }
+        self.probe(|_| {
+            let origin = TypeOrigin::Misc(obligation.cause.span);
+            let err_buf;
+            let mut err = &error.err;
+            let mut values = None;
+
+            // try to find the mismatched types to report the error with.
+            //
+            // this can fail if the problem was higher-ranked, in which
+            // cause I have no idea for a good error message.
+            if let ty::Predicate::Projection(ref data) = predicate {
+                let mut selcx = SelectionContext::new(self);
+                let (data, _) = self.replace_late_bound_regions_with_fresh_var(
+                    obligation.cause.span,
+                    infer::LateBoundRegionConversionTime::HigherRankedType,
+                    data);
+                let normalized = super::normalize_projection_type(
+                    &mut selcx,
+                    data.projection_ty,
+                    obligation.cause.clone(),
+                    0
+                );
+                let origin = TypeOrigin::Misc(obligation.cause.span);
+                if let Err(error) = self.eq_types(
+                    false, origin,
+                    data.ty, normalized.value
+                ) {
+                    values = Some(infer::ValuePairs::Types(ExpectedFound {
+                        expected: normalized.value,
+                        found: data.ty,
+                    }));
+                    err_buf = error;
+                    err = &err_buf;
+                }
+            }
+
+            let mut diag = struct_span_err!(
+                self.tcx.sess, origin.span(), E0271,
+                "type mismatch resolving `{}`", predicate
+            );
+            self.note_type_err(&mut diag, origin, values, err);
+            self.note_obligation_cause(&mut diag, obligation);
+            diag.emit();
+        });
     }
 
     fn impl_substs(&self,
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 56938a7..5444dd9 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -504,7 +504,7 @@
 
     pub fn crate_disambiguator(self, cnum: ast::CrateNum) -> token::InternedString {
         if cnum == LOCAL_CRATE {
-            self.sess.crate_disambiguator.get().as_str()
+            self.sess.local_crate_disambiguator()
         } else {
             self.sess.cstore.crate_disambiguator(cnum)
         }
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index 1e2920c..16a54c2 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -1018,3 +1018,16 @@
         self.generics.visit_with(visitor) || self.ty.visit_with(visitor)
     }
 }
+
+impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::error::ExpectedFound<T> {
+    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
+        ty::error::ExpectedFound {
+            expected: self.expected.fold_with(folder),
+            found: self.found.fold_with(folder),
+        }
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        self.expected.visit_with(visitor) || self.found.visit_with(visitor)
+    }
+}
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index 21c14e6..fadf364 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -182,6 +182,21 @@
         pat_util::arm_contains_ref_binding(arm)
     }
 
+    pub fn has_error_field(self, ty: Ty<'tcx>) -> bool {
+        match ty.sty {
+            ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => {
+                for field in def.all_fields() {
+                    let field_ty = field.ty(self, substs);
+                    if let TyError = field_ty.sty {
+                        return true;
+                    }
+                }
+            }
+            _ => ()
+        }
+        false
+    }
+
     /// Returns the type of element at index `i` in tuple or tuple-like type `t`.
     /// For an enum `t`, `variant` is None only if `t` is a univariant enum.
     pub fn positional_element_ty(self,
diff --git a/src/librustc/util/fs.rs b/src/librustc/util/fs.rs
index 4936e04..f4e1c06 100644
--- a/src/librustc/util/fs.rs
+++ b/src/librustc/util/fs.rs
@@ -10,6 +10,8 @@
 
 use std::path::{self, Path, PathBuf};
 use std::ffi::OsString;
+use std::fs;
+use std::io;
 
 // Unfortunately, on windows, it looks like msvcrt.dll is silently translating
 // verbatim paths under the hood to non-verbatim paths! This manifests itself as
@@ -53,3 +55,15 @@
         _ => p.to_path_buf(),
     }
 }
+
+/// Copy `p` into `q`, preferring to use hard-linking if possible. If
+/// `q` already exists, it is removed first.
+pub fn link_or_copy<P: AsRef<Path>, Q: AsRef<Path>>(p: P, q: Q) -> io::Result<()> {
+    let p = p.as_ref();
+    let q = q.as_ref();
+    if q.exists() {
+        try!(fs::remove_file(&q));
+    }
+    fs::hard_link(p, q)
+        .or_else(|_| fs::copy(p, q).map(|_| ()))
+}
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 0bfb7c1..60977a8 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -974,7 +974,9 @@
             ty::TyVar(ref vid) if print_var_ids => write!(f, "{:?}", vid),
             ty::IntVar(ref vid) if print_var_ids => write!(f, "{:?}", vid),
             ty::FloatVar(ref vid) if print_var_ids => write!(f, "{:?}", vid),
-            ty::TyVar(_) | ty::IntVar(_) | ty::FloatVar(_) => write!(f, "_"),
+            ty::TyVar(_) => write!(f, "_"),
+            ty::IntVar(_) => write!(f, "{}", "{integer}"),
+            ty::FloatVar(_) => write!(f, "{}", "{float}"),
             ty::FreshTy(v) => write!(f, "FreshTy({})", v),
             ty::FreshIntTy(v) => write!(f, "FreshIntTy({})", v),
             ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({})", v)
diff --git a/src/librustc_back/target/aarch64_apple_ios.rs b/src/librustc_back/target/aarch64_apple_ios.rs
index 481338d..6530ccb 100644
--- a/src/librustc_back/target/aarch64_apple_ios.rs
+++ b/src/librustc_back/target/aarch64_apple_ios.rs
@@ -8,11 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::{Target, TargetOptions};
+use target::{Target, TargetOptions, TargetResult};
 use super::apple_ios_base::{opts, Arch};
 
-pub fn target() -> Target {
-    Target {
+pub fn target() -> TargetResult {
+    let base = try!(opts(Arch::Arm64));
+    Ok(Target {
         llvm_target: "arm64-apple-ios".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
@@ -25,7 +26,7 @@
             features: "+neon,+fp-armv8,+cyclone".to_string(),
             eliminate_frame_pointer: false,
             max_atomic_width: 128,
-            .. opts(Arch::Arm64)
+            .. base
         },
-    }
+    })
 }
diff --git a/src/librustc_back/target/aarch64_linux_android.rs b/src/librustc_back/target/aarch64_linux_android.rs
index 81be546..7f54dab 100644
--- a/src/librustc_back/target/aarch64_linux_android.rs
+++ b/src/librustc_back/target/aarch64_linux_android.rs
@@ -8,23 +8,23 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::android_base::opts();
     base.max_atomic_width = 128;
     // As documented in http://developer.android.com/ndk/guides/cpu-features.html
     // the neon (ASIMD) and FP must exist on all android aarch64 targets.
     base.features = "+neon,+fp-armv8".to_string();
-    Target {
+    Ok(Target {
         llvm_target: "aarch64-linux-android".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
-        data_layout: "e-m:e-i64:64-i128:128-n32:64-S128".to_string(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
         arch: "aarch64".to_string(),
         target_os: "android".to_string(),
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
         options: base,
-    }
+    })
 }
diff --git a/src/librustc_back/target/aarch64_unknown_linux_gnu.rs b/src/librustc_back/target/aarch64_unknown_linux_gnu.rs
index aec1bae..cca965f 100644
--- a/src/librustc_back/target/aarch64_unknown_linux_gnu.rs
+++ b/src/librustc_back/target/aarch64_unknown_linux_gnu.rs
@@ -8,20 +8,20 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
     base.max_atomic_width = 128;
-    Target {
+    Ok(Target {
         llvm_target: "aarch64-unknown-linux-gnu".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
         target_env: "gnu".to_string(),
-        data_layout: "e-m:e-i64:64-i128:128-n32:64-S128".to_string(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
         arch: "aarch64".to_string(),
         target_os: "linux".to_string(),
         target_vendor: "unknown".to_string(),
         options: base,
-    }
+    })
 }
diff --git a/src/librustc_back/target/apple_ios_base.rs b/src/librustc_back/target/apple_ios_base.rs
index d182fd9..8bd9fea 100644
--- a/src/librustc_back/target/apple_ios_base.rs
+++ b/src/librustc_back/target/apple_ios_base.rs
@@ -36,7 +36,7 @@
     }
 }
 
-pub fn get_sdk_root(sdk_name: &str) -> String {
+pub fn get_sdk_root(sdk_name: &str) -> Result<String, String> {
     let res = Command::new("xcrun")
                       .arg("--show-sdk-path")
                       .arg("-sdk")
@@ -55,12 +55,12 @@
                       });
 
     match res {
-        Ok(output) => output.trim().to_string(),
-        Err(e) => panic!("failed to get {} SDK path: {}", sdk_name, e)
+        Ok(output) => Ok(output.trim().to_string()),
+        Err(e) => Err(format!("failed to get {} SDK path: {}", sdk_name, e))
     }
 }
 
-fn pre_link_args(arch: Arch) -> Vec<String> {
+fn build_pre_link_args(arch: Arch) -> Result<Vec<String>, String> {
     let sdk_name = match arch {
         Armv7 | Armv7s | Arm64 => "iphoneos",
         I386 | X86_64 => "iphonesimulator"
@@ -68,8 +68,10 @@
 
     let arch_name = arch.to_string();
 
-    vec!["-arch".to_string(), arch_name.to_string(),
-         "-Wl,-syslibroot".to_string(), get_sdk_root(sdk_name)]
+    let sdk_root = try!(get_sdk_root(sdk_name));
+
+    Ok(vec!["-arch".to_string(), arch_name.to_string(),
+         "-Wl,-syslibroot".to_string(), sdk_root])
 }
 
 fn target_cpu(arch: Arch) -> String {
@@ -82,13 +84,14 @@
     }.to_string()
 }
 
-pub fn opts(arch: Arch) -> TargetOptions {
-    TargetOptions {
+pub fn opts(arch: Arch) -> Result<TargetOptions, String> {
+    let pre_link_args = try!(build_pre_link_args(arch));
+    Ok(TargetOptions {
         cpu: target_cpu(arch),
         dynamic_linking: false,
         executables: true,
-        pre_link_args: pre_link_args(arch),
+        pre_link_args: pre_link_args,
         has_elf_tls: false,
         .. super::apple_base::opts()
-    }
+    })
 }
diff --git a/src/librustc_back/target/arm_linux_androideabi.rs b/src/librustc_back/target/arm_linux_androideabi.rs
index e1b1704..f3a18b1 100644
--- a/src/librustc_back/target/arm_linux_androideabi.rs
+++ b/src/librustc_back/target/arm_linux_androideabi.rs
@@ -8,14 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::android_base::opts();
     base.features = "+v7,+vfp3,+d16".to_string();
     base.max_atomic_width = 64;
 
-    Target {
+    Ok(Target {
         llvm_target: "arm-linux-androideabi".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -25,5 +25,5 @@
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
         options: base,
-    }
+    })
 }
diff --git a/src/librustc_back/target/arm_unknown_linux_gnueabi.rs b/src/librustc_back/target/arm_unknown_linux_gnueabi.rs
index 60c4a7c..e666a84 100644
--- a/src/librustc_back/target/arm_unknown_linux_gnueabi.rs
+++ b/src/librustc_back/target/arm_unknown_linux_gnueabi.rs
@@ -8,12 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::{Target, TargetOptions};
+use target::{Target, TargetOptions, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
     base.max_atomic_width = 64;
-    Target {
+    Ok(Target {
         llvm_target: "arm-unknown-linux-gnueabi".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -27,5 +27,5 @@
             features: "+v6".to_string(),
             .. base
         },
-    }
+    })
 }
diff --git a/src/librustc_back/target/arm_unknown_linux_gnueabihf.rs b/src/librustc_back/target/arm_unknown_linux_gnueabihf.rs
index 72128e3..d65c89a 100644
--- a/src/librustc_back/target/arm_unknown_linux_gnueabihf.rs
+++ b/src/librustc_back/target/arm_unknown_linux_gnueabihf.rs
@@ -8,12 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::{Target, TargetOptions};
+use target::{Target, TargetOptions, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
     base.max_atomic_width = 64;
-    Target {
+    Ok(Target {
         llvm_target: "arm-unknown-linux-gnueabihf".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -27,5 +27,5 @@
             features: "+v6,+vfp2".to_string(),
             .. base
         }
-    }
+    })
 }
diff --git a/src/librustc_back/target/arm_unknown_linux_musleabi.rs b/src/librustc_back/target/arm_unknown_linux_musleabi.rs
new file mode 100644
index 0000000..028c91e
--- /dev/null
+++ b/src/librustc_back/target/arm_unknown_linux_musleabi.rs
@@ -0,0 +1,34 @@
+// 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.
+
+use target::{Target, TargetResult};
+
+pub fn target() -> TargetResult {
+    let mut base = super::linux_musl_base::opts();
+
+    // Most of these settings are copied from the arm_unknown_linux_gnueabi
+    // target.
+    base.features = "+v6".to_string();
+    base.max_atomic_width = 64;
+    Ok(Target {
+        // It's important we use "gnueabi" and not "musleabi" here. LLVM uses it
+        // to determine the calling convention and float ABI, and it doesn't
+        // support the "musleabi" value.
+        llvm_target: "arm-unknown-linux-gnueabi".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "32".to_string(),
+        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        arch: "arm".to_string(),
+        target_os: "linux".to_string(),
+        target_env: "musl".to_string(),
+        target_vendor: "unknown".to_string(),
+        options: base,
+    })
+}
diff --git a/src/librustc_back/target/arm_unknown_linux_musleabihf.rs b/src/librustc_back/target/arm_unknown_linux_musleabihf.rs
new file mode 100644
index 0000000..c7dda18
--- /dev/null
+++ b/src/librustc_back/target/arm_unknown_linux_musleabihf.rs
@@ -0,0 +1,34 @@
+// 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.
+
+use target::{Target, TargetResult};
+
+pub fn target() -> TargetResult {
+    let mut base = super::linux_musl_base::opts();
+
+    // Most of these settings are copied from the arm_unknown_linux_gnueabihf
+    // target.
+    base.features = "+v6,+vfp2".to_string();
+    base.max_atomic_width = 64;
+    Ok(Target {
+        // It's important we use "gnueabihf" and not "musleabihf" here. LLVM
+        // uses it to determine the calling convention and float ABI, and it
+        // doesn't support the "musleabihf" value.
+        llvm_target: "arm-unknown-linux-gnueabihf".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "32".to_string(),
+        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        arch: "arm".to_string(),
+        target_os: "linux".to_string(),
+        target_env: "musl".to_string(),
+        target_vendor: "unknown".to_string(),
+        options: base,
+    })
+}
diff --git a/src/librustc_back/target/armv7_apple_ios.rs b/src/librustc_back/target/armv7_apple_ios.rs
index a2486a1..a806204 100644
--- a/src/librustc_back/target/armv7_apple_ios.rs
+++ b/src/librustc_back/target/armv7_apple_ios.rs
@@ -8,11 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::{Target, TargetOptions};
+use target::{Target, TargetOptions, TargetResult};
 use super::apple_ios_base::{opts, Arch};
 
-pub fn target() -> Target {
-    Target {
+pub fn target() -> TargetResult {
+    let base = try!(opts(Arch::Armv7));
+    Ok(Target {
         llvm_target: "armv7-apple-ios".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -24,7 +25,7 @@
         options: TargetOptions {
             features: "+v7,+vfp3,+neon".to_string(),
             max_atomic_width: 64,
-            .. opts(Arch::Armv7)
+            .. base
         }
-    }
+    })
 }
diff --git a/src/librustc_back/target/armv7_linux_androideabi.rs b/src/librustc_back/target/armv7_linux_androideabi.rs
index fd8f35d..1c59262 100644
--- a/src/librustc_back/target/armv7_linux_androideabi.rs
+++ b/src/librustc_back/target/armv7_linux_androideabi.rs
@@ -8,14 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::android_base::opts();
     base.features = "+v7,+thumb2,+vfp3,+d16".to_string();
     base.max_atomic_width = 64;
 
-    Target {
+    Ok(Target {
         llvm_target: "armv7-none-linux-android".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -25,5 +25,5 @@
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
         options: base,
-    }
+    })
 }
diff --git a/src/librustc_back/target/armv7_unknown_linux_gnueabihf.rs b/src/librustc_back/target/armv7_unknown_linux_gnueabihf.rs
index 7bcca3a..52269f0 100644
--- a/src/librustc_back/target/armv7_unknown_linux_gnueabihf.rs
+++ b/src/librustc_back/target/armv7_unknown_linux_gnueabihf.rs
@@ -8,11 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::{Target, TargetOptions};
+use target::{Target, TargetOptions, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let base = super::linux_base::opts();
-    Target {
+    Ok(Target {
         llvm_target: "armv7-unknown-linux-gnueabihf".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -28,6 +28,6 @@
             max_atomic_width: 64,
             .. base
         }
-    }
+    })
 }
 
diff --git a/src/librustc_back/target/armv7_unknown_linux_musleabihf.rs b/src/librustc_back/target/armv7_unknown_linux_musleabihf.rs
new file mode 100644
index 0000000..e40704e
--- /dev/null
+++ b/src/librustc_back/target/armv7_unknown_linux_musleabihf.rs
@@ -0,0 +1,35 @@
+// 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.
+
+use target::{Target, TargetResult};
+
+pub fn target() -> TargetResult {
+    let mut base = super::linux_musl_base::opts();
+
+    // Most of these settings are copied from the armv7_unknown_linux_gnueabihf
+    // target.
+    base.features = "+v7,+vfp3,+neon".to_string();
+    base.cpu = "cortex-a8".to_string();
+    base.max_atomic_width = 64;
+    Ok(Target {
+        // It's important we use "gnueabihf" and not "musleabihf" here. LLVM
+        // uses it to determine the calling convention and float ABI, and LLVM
+        // doesn't support the "musleabihf" value.
+        llvm_target: "armv7-unknown-linux-gnueabihf".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "32".to_string(),
+        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        arch: "arm".to_string(),
+        target_os: "linux".to_string(),
+        target_env: "musl".to_string(),
+        target_vendor: "unknown".to_string(),
+        options: base,
+    })
+}
diff --git a/src/librustc_back/target/armv7s_apple_ios.rs b/src/librustc_back/target/armv7s_apple_ios.rs
index e5379aa..aaa3570 100644
--- a/src/librustc_back/target/armv7s_apple_ios.rs
+++ b/src/librustc_back/target/armv7s_apple_ios.rs
@@ -8,11 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::{Target, TargetOptions};
+use target::{Target, TargetOptions, TargetResult};
 use super::apple_ios_base::{opts, Arch};
 
-pub fn target() -> Target {
-    Target {
+pub fn target() -> TargetResult {
+    let base = try!(opts(Arch::Armv7s));
+    Ok(Target {
         llvm_target: "armv7s-apple-ios".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -24,7 +25,7 @@
         options: TargetOptions {
             features: "+v7,+vfp4,+neon".to_string(),
             max_atomic_width: 64,
-            .. opts(Arch::Armv7s)
+            .. base
         }
-    }
+    })
 }
diff --git a/src/librustc_back/target/asmjs_unknown_emscripten.rs b/src/librustc_back/target/asmjs_unknown_emscripten.rs
index e620017..07eb191 100644
--- a/src/librustc_back/target/asmjs_unknown_emscripten.rs
+++ b/src/librustc_back/target/asmjs_unknown_emscripten.rs
@@ -10,7 +10,7 @@
 
 use super::{Target, TargetOptions};
 
-pub fn target() -> Target {
+pub fn target() -> Result<Target, String> {
     let opts = TargetOptions {
         linker: "emcc".to_string(),
         ar: "emar".to_string(),
@@ -25,7 +25,7 @@
         max_atomic_width: 32,
         .. Default::default()
     };
-    Target {
+    Ok(Target {
         llvm_target: "asmjs-unknown-emscripten".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -35,5 +35,5 @@
         data_layout: "e-p:32:32-i64:64-v128:32:128-n32-S128".to_string(),
         arch: "asmjs".to_string(),
         options: opts,
-    }
+    })
 }
diff --git a/src/librustc_back/target/i386_apple_ios.rs b/src/librustc_back/target/i386_apple_ios.rs
index cf4020e..f391d41 100644
--- a/src/librustc_back/target/i386_apple_ios.rs
+++ b/src/librustc_back/target/i386_apple_ios.rs
@@ -8,11 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::{Target, TargetOptions};
+use target::{Target, TargetOptions, TargetResult};
 use super::apple_ios_base::{opts, Arch};
 
-pub fn target() -> Target {
-    Target {
+pub fn target() -> TargetResult {
+    let base = try!(opts(Arch::I386));
+    Ok(Target {
         llvm_target: "i386-apple-ios".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -23,7 +24,7 @@
         target_vendor: "apple".to_string(),
         options: TargetOptions {
             max_atomic_width: 64,
-            .. opts(Arch::I386)
+            .. base
         }
-    }
+    })
 }
diff --git a/src/librustc_back/target/i586_pc_windows_msvc.rs b/src/librustc_back/target/i586_pc_windows_msvc.rs
index 12bed37..445ee6c 100644
--- a/src/librustc_back/target/i586_pc_windows_msvc.rs
+++ b/src/librustc_back/target/i586_pc_windows_msvc.rs
@@ -8,11 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::TargetResult;
 
-pub fn target() -> Target {
-    let mut base = super::i686_pc_windows_msvc::target();
+pub fn target() -> TargetResult {
+    let mut base = try!(super::i686_pc_windows_msvc::target());
     base.options.cpu = "pentium".to_string();
     base.llvm_target = "i586-pc-windows-msvc".to_string();
-    return base
+    Ok(base)
 }
diff --git a/src/librustc_back/target/i586_unknown_linux_gnu.rs b/src/librustc_back/target/i586_unknown_linux_gnu.rs
index 6eb64556..1ca8606 100644
--- a/src/librustc_back/target/i586_unknown_linux_gnu.rs
+++ b/src/librustc_back/target/i586_unknown_linux_gnu.rs
@@ -8,11 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::TargetResult;
 
-pub fn target() -> Target {
-    let mut base = super::i686_unknown_linux_gnu::target();
+pub fn target() -> TargetResult {
+    let mut base = try!(super::i686_unknown_linux_gnu::target());
     base.options.cpu = "pentium".to_string();
     base.llvm_target = "i586-unknown-linux-gnu".to_string();
-    return base
+    Ok(base)
 }
diff --git a/src/librustc_back/target/i686_apple_darwin.rs b/src/librustc_back/target/i686_apple_darwin.rs
index 302691e..4876a34 100644
--- a/src/librustc_back/target/i686_apple_darwin.rs
+++ b/src/librustc_back/target/i686_apple_darwin.rs
@@ -8,15 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::apple_base::opts();
     base.cpu = "yonah".to_string();
     base.max_atomic_width = 64;
     base.pre_link_args.push("-m32".to_string());
 
-    Target {
+    Ok(Target {
         llvm_target: "i686-apple-darwin".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -26,5 +26,5 @@
         target_env: "".to_string(),
         target_vendor: "apple".to_string(),
         options: base,
-    }
+    })
 }
diff --git a/src/librustc_back/target/i686_linux_android.rs b/src/librustc_back/target/i686_linux_android.rs
index 2376de1..1de6292 100644
--- a/src/librustc_back/target/i686_linux_android.rs
+++ b/src/librustc_back/target/i686_linux_android.rs
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::android_base::opts();
 
     base.max_atomic_width = 64;
@@ -19,7 +19,7 @@
     base.cpu = "pentiumpro".to_string();
     base.features = "+mmx,+sse,+sse2,+sse3,+ssse3".to_string();
 
-    Target {
+    Ok(Target {
         llvm_target: "i686-linux-android".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -29,5 +29,5 @@
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
         options: base,
-    }
+    })
 }
diff --git a/src/librustc_back/target/i686_pc_windows_gnu.rs b/src/librustc_back/target/i686_pc_windows_gnu.rs
index c2cc624..2c19b81 100644
--- a/src/librustc_back/target/i686_pc_windows_gnu.rs
+++ b/src/librustc_back/target/i686_pc_windows_gnu.rs
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::windows_base::opts();
     base.cpu = "pentium4".to_string();
     base.max_atomic_width = 64;
@@ -19,7 +19,7 @@
     // space available to x86 Windows binaries on x86_64.
     base.pre_link_args.push("-Wl,--large-address-aware".to_string());
 
-    Target {
+    Ok(Target {
         llvm_target: "i686-pc-windows-gnu".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -29,5 +29,5 @@
         target_env: "gnu".to_string(),
         target_vendor: "pc".to_string(),
         options: base,
-    }
+    })
 }
diff --git a/src/librustc_back/target/i686_pc_windows_msvc.rs b/src/librustc_back/target/i686_pc_windows_msvc.rs
index 8c1bacc..cb02fcc 100644
--- a/src/librustc_back/target/i686_pc_windows_msvc.rs
+++ b/src/librustc_back/target/i686_pc_windows_msvc.rs
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::windows_msvc_base::opts();
     base.cpu = "pentium4".to_string();
     base.max_atomic_width = 64;
@@ -24,7 +24,7 @@
     // https://msdn.microsoft.com/en-us/library/9a89h429.aspx
     base.pre_link_args.push("/SAFESEH".to_string());
 
-    Target {
+    Ok(Target {
         llvm_target: "i686-pc-windows-msvc".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -34,5 +34,5 @@
         target_env: "msvc".to_string(),
         target_vendor: "pc".to_string(),
         options: base,
-    }
+    })
 }
diff --git a/src/librustc_back/target/i686_unknown_dragonfly.rs b/src/librustc_back/target/i686_unknown_dragonfly.rs
index 6446ac4..f96ec00 100644
--- a/src/librustc_back/target/i686_unknown_dragonfly.rs
+++ b/src/librustc_back/target/i686_unknown_dragonfly.rs
@@ -8,15 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::dragonfly_base::opts();
     base.cpu = "pentium4".to_string();
     base.max_atomic_width = 64;
     base.pre_link_args.push("-m32".to_string());
 
-    Target {
+    Ok(Target {
         llvm_target: "i686-unknown-dragonfly".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -26,5 +26,5 @@
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
         options: base,
-    }
+    })
 }
diff --git a/src/librustc_back/target/i686_unknown_freebsd.rs b/src/librustc_back/target/i686_unknown_freebsd.rs
index a7903d5..3489ecf 100644
--- a/src/librustc_back/target/i686_unknown_freebsd.rs
+++ b/src/librustc_back/target/i686_unknown_freebsd.rs
@@ -8,15 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::freebsd_base::opts();
     base.cpu = "pentium4".to_string();
     base.max_atomic_width = 64;
     base.pre_link_args.push("-m32".to_string());
 
-    Target {
+    Ok(Target {
         llvm_target: "i686-unknown-freebsd".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -26,5 +26,5 @@
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
         options: base,
-    }
+    })
 }
diff --git a/src/librustc_back/target/i686_unknown_linux_gnu.rs b/src/librustc_back/target/i686_unknown_linux_gnu.rs
index 7813d55..f2e865c 100644
--- a/src/librustc_back/target/i686_unknown_linux_gnu.rs
+++ b/src/librustc_back/target/i686_unknown_linux_gnu.rs
@@ -8,15 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
     base.cpu = "pentium4".to_string();
     base.max_atomic_width = 64;
     base.pre_link_args.push("-m32".to_string());
 
-    Target {
+    Ok(Target {
         llvm_target: "i686-unknown-linux-gnu".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -26,5 +26,5 @@
         target_env: "gnu".to_string(),
         target_vendor: "unknown".to_string(),
         options: base,
-    }
+    })
 }
diff --git a/src/librustc_back/target/i686_unknown_linux_musl.rs b/src/librustc_back/target/i686_unknown_linux_musl.rs
index 5274429..a0a8de4 100644
--- a/src/librustc_back/target/i686_unknown_linux_musl.rs
+++ b/src/librustc_back/target/i686_unknown_linux_musl.rs
@@ -8,16 +8,16 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::linux_musl_base::opts();
     base.cpu = "pentium4".to_string();
     base.max_atomic_width = 64;
     base.pre_link_args.push("-m32".to_string());
     base.pre_link_args.push("-Wl,-melf_i386".to_string());
 
-    Target {
+    Ok(Target {
         llvm_target: "i686-unknown-linux-musl".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -27,5 +27,5 @@
         target_env: "musl".to_string(),
         target_vendor: "unknown".to_string(),
         options: base,
-    }
+    })
 }
diff --git a/src/librustc_back/target/le32_unknown_nacl.rs b/src/librustc_back/target/le32_unknown_nacl.rs
index f4f0262..25132f8 100644
--- a/src/librustc_back/target/le32_unknown_nacl.rs
+++ b/src/librustc_back/target/le32_unknown_nacl.rs
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use super::{Target, TargetOptions};
+use super::{Target, TargetOptions, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let opts = TargetOptions {
         linker: "pnacl-clang".to_string(),
         ar: "pnacl-ar".to_string(),
@@ -28,7 +28,7 @@
         max_atomic_width: 32,
         .. Default::default()
     };
-    Target {
+    Ok(Target {
         llvm_target: "le32-unknown-nacl".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -38,5 +38,5 @@
         data_layout: "e-i64:64:64-p:32:32:32-v128:32:32".to_string(),
         arch: "le32".to_string(),
         options: opts,
-    }
+    })
 }
diff --git a/src/librustc_back/target/mips_unknown_linux_gnu.rs b/src/librustc_back/target/mips_unknown_linux_gnu.rs
index ceb17e5..ab967f6 100644
--- a/src/librustc_back/target/mips_unknown_linux_gnu.rs
+++ b/src/librustc_back/target/mips_unknown_linux_gnu.rs
@@ -8,10 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::{Target, TargetOptions};
+use target::{Target, TargetOptions, TargetResult};
 
-pub fn target() -> Target {
-    Target {
+pub fn target() -> TargetResult {
+    Ok(Target {
         llvm_target: "mips-unknown-linux-gnu".to_string(),
         target_endian: "big".to_string(),
         target_pointer_width: "32".to_string(),
@@ -26,5 +26,5 @@
             max_atomic_width: 32,
             ..super::linux_base::opts()
         },
-    }
+    })
 }
diff --git a/src/librustc_back/target/mips_unknown_linux_musl.rs b/src/librustc_back/target/mips_unknown_linux_musl.rs
index 3536665..4a69bce 100644
--- a/src/librustc_back/target/mips_unknown_linux_musl.rs
+++ b/src/librustc_back/target/mips_unknown_linux_musl.rs
@@ -8,10 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::{Target, TargetOptions};
+use target::{Target, TargetOptions, TargetResult};
 
-pub fn target() -> Target {
-    Target {
+pub fn target() -> TargetResult {
+    Ok(Target {
         llvm_target: "mips-unknown-linux-musl".to_string(),
         target_endian: "big".to_string(),
         target_pointer_width: "32".to_string(),
@@ -26,5 +26,5 @@
             max_atomic_width: 32,
             ..super::linux_base::opts()
         }
-    }
+    })
 }
diff --git a/src/librustc_back/target/mipsel_unknown_linux_gnu.rs b/src/librustc_back/target/mipsel_unknown_linux_gnu.rs
index ac1536b..b66fb62 100644
--- a/src/librustc_back/target/mipsel_unknown_linux_gnu.rs
+++ b/src/librustc_back/target/mipsel_unknown_linux_gnu.rs
@@ -8,10 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::{Target, TargetOptions};
+use target::{Target, TargetOptions, TargetResult};
 
-pub fn target() -> Target {
-    Target {
+pub fn target() -> TargetResult {
+    Ok(Target {
         llvm_target: "mipsel-unknown-linux-gnu".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -27,5 +27,5 @@
             max_atomic_width: 32,
             ..super::linux_base::opts()
         },
-    }
+    })
 }
diff --git a/src/librustc_back/target/mipsel_unknown_linux_musl.rs b/src/librustc_back/target/mipsel_unknown_linux_musl.rs
index a9ea52c..a0524e5 100644
--- a/src/librustc_back/target/mipsel_unknown_linux_musl.rs
+++ b/src/librustc_back/target/mipsel_unknown_linux_musl.rs
@@ -8,10 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::{Target, TargetOptions};
+use target::{Target, TargetOptions, TargetResult};
 
-pub fn target() -> Target {
-    Target {
+pub fn target() -> TargetResult {
+    Ok(Target {
         llvm_target: "mipsel-unknown-linux-musl".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
@@ -22,9 +22,9 @@
         target_vendor: "unknown".to_string(),
         options: TargetOptions {
             cpu: "mips32".to_string(),
-            features: "+mips32".to_string(),
+            features: "+mips32,+soft-float".to_string(),
             max_atomic_width: 32,
             ..super::linux_base::opts()
         }
-    }
+    })
 }
diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs
index 99bc268..3d24fd8 100644
--- a/src/librustc_back/target/mod.rs
+++ b/src/librustc_back/target/mod.rs
@@ -44,7 +44,8 @@
 //! the target's settings, though `target-feature` and `link-args` will *add*
 //! to the list specified by the target, rather than replace.
 
-use serialize::json::Json;
+use serialize::json::{Json, ToJson};
+use std::collections::BTreeMap;
 use std::default::Default;
 use std::io::prelude::*;
 use syntax::abi::Abi;
@@ -63,26 +64,62 @@
 mod windows_base;
 mod windows_msvc_base;
 
+pub type TargetResult = Result<Target, String>;
+
 macro_rules! supported_targets {
     ( $(($triple:expr, $module:ident)),+ ) => (
         $(mod $module;)*
 
         /// List of supported targets
-        pub const TARGETS: &'static [&'static str] = &[$($triple),*];
+        const TARGETS: &'static [&'static str] = &[$($triple),*];
 
-        fn load_specific(target: &str) -> Option<Target> {
+        fn load_specific(target: &str) -> TargetResult {
             match target {
                 $(
                     $triple => {
-                        let mut t = $module::target();
+                        let mut t = try!($module::target());
                         t.options.is_builtin = true;
+
+                        // round-trip through the JSON parser to ensure at
+                        // run-time that the parser works correctly
+                        t = try!(Target::from_json(t.to_json()));
                         debug!("Got builtin target: {:?}", t);
-                        Some(t)
+                        Ok(t)
                     },
                 )+
-                _ => None
+                _ => Err(format!("Unable to find target: {}", target))
             }
         }
+
+        pub fn get_targets() -> Box<Iterator<Item=String>> {
+            Box::new(TARGETS.iter().filter_map(|t| -> Option<String> {
+                load_specific(t)
+                    .map(|t| t.llvm_target)
+                    .ok()
+            }))
+        }
+
+        #[cfg(test)]
+        mod test_json_encode_decode {
+            use serialize::json::ToJson;
+            use super::Target;
+            $(use super::$module;)*
+
+            $(
+                #[test]
+                fn $module() {
+                    // Grab the TargetResult struct. If we successfully retrieved
+                    // a Target, then the test JSON encoding/decoding can run for this
+                    // Target on this testing platform (i.e., checking the iOS targets
+                    // only on a Mac test platform).
+                    let _ = $module::target().map(|original| {
+                        let as_json = original.to_json();
+                        let parsed = Target::from_json(as_json).unwrap();
+                        assert_eq!(original, parsed);
+                    });
+                }
+            )*
+        }
     )
 }
 
@@ -97,7 +134,10 @@
     ("powerpc64le-unknown-linux-gnu", powerpc64le_unknown_linux_gnu),
     ("arm-unknown-linux-gnueabi", arm_unknown_linux_gnueabi),
     ("arm-unknown-linux-gnueabihf", arm_unknown_linux_gnueabihf),
+    ("arm-unknown-linux-musleabi", arm_unknown_linux_musleabi),
+    ("arm-unknown-linux-musleabihf", arm_unknown_linux_musleabihf),
     ("armv7-unknown-linux-gnueabihf", armv7_unknown_linux_gnueabihf),
+    ("armv7-unknown-linux-musleabihf", armv7_unknown_linux_musleabihf),
     ("aarch64-unknown-linux-gnu", aarch64_unknown_linux_gnu),
     ("x86_64-unknown-linux-musl", x86_64_unknown_linux_musl),
     ("i686-unknown-linux-musl", i686_unknown_linux_musl),
@@ -145,7 +185,7 @@
 /// Everything `rustc` knows about how to compile for a specific target.
 ///
 /// Every field here must be specified, and has no default value.
-#[derive(Clone, Debug)]
+#[derive(PartialEq, Clone, Debug)]
 pub struct Target {
     /// Target triple to pass to LLVM.
     pub llvm_target: String,
@@ -172,7 +212,7 @@
 ///
 /// This has an implementation of `Default`, see each field for what the default is. In general,
 /// these try to take "minimal defaults" that don't assume anything about the runtime they run in.
-#[derive(Clone, Debug)]
+#[derive(PartialEq, Clone, Debug)]
 pub struct TargetOptions {
     /// Whether the target is built-in or loaded from a custom target specification.
     pub is_builtin: bool,
@@ -252,6 +292,13 @@
     pub is_like_android: bool,
     /// Whether the linker support GNU-like arguments such as -O. Defaults to false.
     pub linker_is_gnu: bool,
+    /// The MinGW toolchain has a known issue that prevents it from correctly
+    /// handling COFF object files with more than 2^15 sections. Since each weak
+    /// symbol needs its own COMDAT section, weak linkage implies a large
+    /// number sections that easily exceeds the given limit for larger
+    /// codebases. Consequently we want a way to disallow weak linkage on some
+    /// platforms.
+    pub allows_weak_linkage: bool,
     /// Whether the linker support rpaths or not. Defaults to false.
     pub has_rpath: bool,
     /// Whether to disable linking to compiler-rt. Defaults to false, as LLVM
@@ -327,6 +374,7 @@
             is_like_android: false,
             is_like_msvc: false,
             linker_is_gnu: false,
+            allows_weak_linkage: true,
             has_rpath: false,
             no_compiler_rt: false,
             no_default_libraries: true,
@@ -363,16 +411,21 @@
     }
 
     /// Load a target descriptor from a JSON object.
-    pub fn from_json(obj: Json) -> Target {
-        // this is 1. ugly, 2. error prone.
+    pub fn from_json(obj: Json) -> TargetResult {
+        // While ugly, this code must remain this way to retain
+        // compatibility with existing JSON fields and the internal
+        // expected naming of the Target and TargetOptions structs.
+        // To ensure compatibility is retained, the built-in targets
+        // are round-tripped through this code to catch cases where
+        // the JSON parser is not updated to match the structs.
 
         let get_req_field = |name: &str| {
             match obj.find(name)
                      .map(|s| s.as_string())
                      .and_then(|os| os.map(|s| s.to_string())) {
-                Some(val) => val,
+                Some(val) => Ok(val),
                 None => {
-                    panic!("Field {} in target specification is required", name)
+                    return Err(format!("Field {} in target specification is required", name))
                 }
             }
         };
@@ -384,12 +437,12 @@
         };
 
         let mut base = Target {
-            llvm_target: get_req_field("llvm-target"),
-            target_endian: get_req_field("target-endian"),
-            target_pointer_width: get_req_field("target-pointer-width"),
-            data_layout: get_req_field("data-layout"),
-            arch: get_req_field("arch"),
-            target_os: get_req_field("os"),
+            llvm_target: try!(get_req_field("llvm-target")),
+            target_endian: try!(get_req_field("target-endian")),
+            target_pointer_width: try!(get_req_field("target-pointer-width")),
+            data_layout: try!(get_req_field("data-layout")),
+            arch: try!(get_req_field("arch")),
+            target_os: try!(get_req_field("os")),
             target_env: get_opt_field("env", ""),
             target_vendor: get_opt_field("vendor", "unknown"),
             options: Default::default(),
@@ -434,38 +487,51 @@
             } );
         }
 
-        key!(cpu);
-        key!(ar);
+        key!(is_builtin, bool);
         key!(linker);
+        key!(ar);
+        key!(pre_link_args, list);
+        key!(pre_link_objects_exe, list);
+        key!(pre_link_objects_dll, list);
+        key!(late_link_args, list);
+        key!(post_link_objects, list);
+        key!(post_link_args, list);
+        key!(cpu);
+        key!(features);
+        key!(dynamic_linking, bool);
+        key!(executables, bool);
         key!(relocation_model);
         key!(code_model);
+        key!(disable_redzone, bool);
+        key!(eliminate_frame_pointer, bool);
+        key!(function_sections, bool);
         key!(dll_prefix);
         key!(dll_suffix);
         key!(exe_suffix);
         key!(staticlib_prefix);
         key!(staticlib_suffix);
-        key!(features);
-        key!(dynamic_linking, bool);
-        key!(executables, bool);
-        key!(disable_redzone, bool);
-        key!(eliminate_frame_pointer, bool);
-        key!(function_sections, bool);
         key!(target_family, optional);
         key!(is_like_osx, bool);
+        key!(is_like_solaris, bool);
         key!(is_like_windows, bool);
         key!(is_like_msvc, bool);
+        key!(is_like_android, bool);
         key!(linker_is_gnu, bool);
+        key!(allows_weak_linkage, bool);
         key!(has_rpath, bool);
         key!(no_compiler_rt, bool);
         key!(no_default_libraries, bool);
-        key!(pre_link_args, list);
-        key!(post_link_args, list);
+        key!(position_independent_executables, bool);
         key!(archive_format);
         key!(allow_asm, bool);
         key!(custom_unwind_resume, bool);
+        key!(lib_allocation_crate);
+        key!(exe_allocation_crate);
+        key!(has_elf_tls, bool);
+        key!(obj_is_bitcode, bool);
         key!(max_atomic_width, u64);
 
-        base
+        Ok(base)
     }
 
     /// Search RUST_TARGET_PATH for a JSON file specifying the given target
@@ -488,10 +554,10 @@
             f.read_to_end(&mut contents).map_err(|e| e.to_string())?;
             let obj = json::from_reader(&mut &contents[..])
                            .map_err(|e| e.to_string())?;
-            Ok(Target::from_json(obj))
+            Target::from_json(obj)
         }
 
-        if let Some(t) = load_specific(target) {
+        if let Ok(t) = load_specific(target) {
             return Ok(t)
         }
 
@@ -523,6 +589,95 @@
     }
 }
 
+impl ToJson for Target {
+    fn to_json(&self) -> Json {
+        let mut d = BTreeMap::new();
+        let default: TargetOptions = Default::default();
+
+        macro_rules! target_val {
+            ($attr:ident) => ( {
+                let name = (stringify!($attr)).replace("_", "-");
+                d.insert(name.to_string(), self.$attr.to_json());
+            } );
+            ($attr:ident, $key_name:expr) => ( {
+                let name = $key_name;
+                d.insert(name.to_string(), self.$attr.to_json());
+            } );
+        }
+
+        macro_rules! target_option_val {
+            ($attr:ident) => ( {
+                let name = (stringify!($attr)).replace("_", "-");
+                if default.$attr != self.options.$attr {
+                    d.insert(name.to_string(), self.options.$attr.to_json());
+                }
+            } );
+            ($attr:ident, $key_name:expr) => ( {
+                let name = $key_name;
+                if default.$attr != self.options.$attr {
+                    d.insert(name.to_string(), self.options.$attr.to_json());
+                }
+            } );
+        }
+
+        target_val!(llvm_target);
+        target_val!(target_endian);
+        target_val!(target_pointer_width);
+        target_val!(arch);
+        target_val!(target_os, "os");
+        target_val!(target_env, "env");
+        target_val!(target_vendor, "vendor");
+        target_val!(arch);
+        target_val!(data_layout);
+
+        target_option_val!(is_builtin);
+        target_option_val!(linker);
+        target_option_val!(ar);
+        target_option_val!(pre_link_args);
+        target_option_val!(pre_link_objects_exe);
+        target_option_val!(pre_link_objects_dll);
+        target_option_val!(late_link_args);
+        target_option_val!(post_link_objects);
+        target_option_val!(post_link_args);
+        target_option_val!(cpu);
+        target_option_val!(features);
+        target_option_val!(dynamic_linking);
+        target_option_val!(executables);
+        target_option_val!(relocation_model);
+        target_option_val!(code_model);
+        target_option_val!(disable_redzone);
+        target_option_val!(eliminate_frame_pointer);
+        target_option_val!(function_sections);
+        target_option_val!(dll_prefix);
+        target_option_val!(dll_suffix);
+        target_option_val!(exe_suffix);
+        target_option_val!(staticlib_prefix);
+        target_option_val!(staticlib_suffix);
+        target_option_val!(target_family);
+        target_option_val!(is_like_osx);
+        target_option_val!(is_like_solaris);
+        target_option_val!(is_like_windows);
+        target_option_val!(is_like_msvc);
+        target_option_val!(is_like_android);
+        target_option_val!(linker_is_gnu);
+        target_option_val!(allows_weak_linkage);
+        target_option_val!(has_rpath);
+        target_option_val!(no_compiler_rt);
+        target_option_val!(no_default_libraries);
+        target_option_val!(position_independent_executables);
+        target_option_val!(archive_format);
+        target_option_val!(allow_asm);
+        target_option_val!(custom_unwind_resume);
+        target_option_val!(lib_allocation_crate);
+        target_option_val!(exe_allocation_crate);
+        target_option_val!(has_elf_tls);
+        target_option_val!(obj_is_bitcode);
+        target_option_val!(max_atomic_width);
+
+        Json::Object(d)
+    }
+}
+
 fn maybe_jemalloc() -> String {
     if cfg!(feature = "jemalloc") {
         "alloc_jemalloc".to_string()
diff --git a/src/librustc_back/target/powerpc64_unknown_linux_gnu.rs b/src/librustc_back/target/powerpc64_unknown_linux_gnu.rs
index be4be8e..1c04e76 100644
--- a/src/librustc_back/target/powerpc64_unknown_linux_gnu.rs
+++ b/src/librustc_back/target/powerpc64_unknown_linux_gnu.rs
@@ -8,15 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
     base.cpu = "ppc64".to_string();
     base.pre_link_args.push("-m64".to_string());
     base.max_atomic_width = 64;
 
-    Target {
+    Ok(Target {
         llvm_target: "powerpc64-unknown-linux-gnu".to_string(),
         target_endian: "big".to_string(),
         target_pointer_width: "64".to_string(),
@@ -26,5 +26,5 @@
         target_env: "gnu".to_string(),
         target_vendor: "unknown".to_string(),
         options: base,
-    }
+    })
 }
diff --git a/src/librustc_back/target/powerpc64le_unknown_linux_gnu.rs b/src/librustc_back/target/powerpc64le_unknown_linux_gnu.rs
index b0a81ce..906e28d 100644
--- a/src/librustc_back/target/powerpc64le_unknown_linux_gnu.rs
+++ b/src/librustc_back/target/powerpc64le_unknown_linux_gnu.rs
@@ -8,15 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
     base.cpu = "ppc64le".to_string();
     base.pre_link_args.push("-m64".to_string());
     base.max_atomic_width = 64;
 
-    Target {
+    Ok(Target {
         llvm_target: "powerpc64le-unknown-linux-gnu".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
@@ -26,5 +26,5 @@
         target_env: "gnu".to_string(),
         target_vendor: "unknown".to_string(),
         options: base,
-    }
+    })
 }
diff --git a/src/librustc_back/target/powerpc_unknown_linux_gnu.rs b/src/librustc_back/target/powerpc_unknown_linux_gnu.rs
index aea57dc..aebf9cd 100644
--- a/src/librustc_back/target/powerpc_unknown_linux_gnu.rs
+++ b/src/librustc_back/target/powerpc_unknown_linux_gnu.rs
@@ -8,14 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
     base.pre_link_args.push("-m32".to_string());
     base.max_atomic_width = 32;
 
-    Target {
+    Ok(Target {
         llvm_target: "powerpc-unknown-linux-gnu".to_string(),
         target_endian: "big".to_string(),
         target_pointer_width: "32".to_string(),
@@ -25,5 +25,5 @@
         target_env: "gnu".to_string(),
         target_vendor: "unknown".to_string(),
         options: base,
-    }
+    })
 }
diff --git a/src/librustc_back/target/windows_base.rs b/src/librustc_back/target/windows_base.rs
index 1e46f45..c398ee4 100644
--- a/src/librustc_back/target/windows_base.rs
+++ b/src/librustc_back/target/windows_base.rs
@@ -25,6 +25,7 @@
         staticlib_suffix: ".lib".to_string(),
         no_default_libraries: true,
         is_like_windows: true,
+        allows_weak_linkage: false,
         pre_link_args: vec!(
             // And here, we see obscure linker flags #45. On windows, it has been
             // found to be necessary to have this flag to compile liblibc.
diff --git a/src/librustc_back/target/x86_64_apple_darwin.rs b/src/librustc_back/target/x86_64_apple_darwin.rs
index 5542c91..65e4b14 100644
--- a/src/librustc_back/target/x86_64_apple_darwin.rs
+++ b/src/librustc_back/target/x86_64_apple_darwin.rs
@@ -8,16 +8,16 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::apple_base::opts();
     base.cpu = "core2".to_string();
     base.max_atomic_width = 128; // core2 support cmpxchg16b
     base.eliminate_frame_pointer = false;
     base.pre_link_args.push("-m64".to_string());
 
-    Target {
+    Ok(Target {
         llvm_target: "x86_64-apple-darwin".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
@@ -27,5 +27,5 @@
         target_env: "".to_string(),
         target_vendor: "apple".to_string(),
         options: base,
-    }
+    })
 }
diff --git a/src/librustc_back/target/x86_64_apple_ios.rs b/src/librustc_back/target/x86_64_apple_ios.rs
index 8638241..4afc9bc 100644
--- a/src/librustc_back/target/x86_64_apple_ios.rs
+++ b/src/librustc_back/target/x86_64_apple_ios.rs
@@ -8,11 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::{Target, TargetOptions};
+use target::{Target, TargetOptions, TargetResult};
 use super::apple_ios_base::{opts, Arch};
 
-pub fn target() -> Target {
-    Target {
+pub fn target() -> TargetResult {
+    let base = try!(opts(Arch::X86_64));
+    Ok(Target {
         llvm_target: "x86_64-apple-ios".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
@@ -23,7 +24,7 @@
         target_vendor: "apple".to_string(),
         options: TargetOptions {
             max_atomic_width: 64,
-            .. opts(Arch::X86_64)
+            .. base
         }
-    }
+    })
 }
diff --git a/src/librustc_back/target/x86_64_pc_windows_gnu.rs b/src/librustc_back/target/x86_64_pc_windows_gnu.rs
index e243054..086e0e6 100644
--- a/src/librustc_back/target/x86_64_pc_windows_gnu.rs
+++ b/src/librustc_back/target/x86_64_pc_windows_gnu.rs
@@ -8,15 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::windows_base::opts();
     base.cpu = "x86-64".to_string();
     base.pre_link_args.push("-m64".to_string());
     base.max_atomic_width = 64;
 
-    Target {
+    Ok(Target {
         llvm_target: "x86_64-pc-windows-gnu".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
@@ -26,5 +26,5 @@
         target_env: "gnu".to_string(),
         target_vendor: "pc".to_string(),
         options: base,
-    }
+    })
 }
diff --git a/src/librustc_back/target/x86_64_pc_windows_msvc.rs b/src/librustc_back/target/x86_64_pc_windows_msvc.rs
index a23a807..064f06e 100644
--- a/src/librustc_back/target/x86_64_pc_windows_msvc.rs
+++ b/src/librustc_back/target/x86_64_pc_windows_msvc.rs
@@ -8,14 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::windows_msvc_base::opts();
     base.cpu = "x86-64".to_string();
     base.max_atomic_width = 64;
 
-    Target {
+    Ok(Target {
         llvm_target: "x86_64-pc-windows-msvc".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
@@ -25,5 +25,5 @@
         target_env: "msvc".to_string(),
         target_vendor: "pc".to_string(),
         options: base,
-    }
+    })
 }
diff --git a/src/librustc_back/target/x86_64_rumprun_netbsd.rs b/src/librustc_back/target/x86_64_rumprun_netbsd.rs
index af5d21c..fd6578c 100644
--- a/src/librustc_back/target/x86_64_rumprun_netbsd.rs
+++ b/src/librustc_back/target/x86_64_rumprun_netbsd.rs
@@ -8,10 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::netbsd_base::opts();
+    base.cpu = "x86-64".to_string();
     base.pre_link_args.push("-m64".to_string());
     base.linker = "x86_64-rumprun-netbsd-gcc".to_string();
     base.ar = "x86_64-rumprun-netbsd-ar".to_string();
@@ -24,7 +25,7 @@
     base.no_default_libraries = false;
     base.exe_allocation_crate = "alloc_system".to_string();
 
-    Target {
+    Ok(Target {
         llvm_target: "x86_64-rumprun-netbsd".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
@@ -34,5 +35,5 @@
         target_env: "".to_string(),
         target_vendor: "rumprun".to_string(),
         options: base,
-    }
+    })
 }
diff --git a/src/librustc_back/target/x86_64_sun_solaris.rs b/src/librustc_back/target/x86_64_sun_solaris.rs
index 8f2c905..2a1feb9 100644
--- a/src/librustc_back/target/x86_64_sun_solaris.rs
+++ b/src/librustc_back/target/x86_64_sun_solaris.rs
@@ -8,15 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::solaris_base::opts();
     base.pre_link_args.push("-m64".to_string());
     base.cpu = "x86-64".to_string();
     base.max_atomic_width = 64;
 
-    Target {
+    Ok(Target {
         llvm_target: "x86_64-pc-solaris".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
@@ -26,5 +26,5 @@
         target_env: "".to_string(),
         target_vendor: "sun".to_string(),
         options: base,
-    }
+    })
 }
diff --git a/src/librustc_back/target/x86_64_unknown_bitrig.rs b/src/librustc_back/target/x86_64_unknown_bitrig.rs
index 87753da..3820965 100644
--- a/src/librustc_back/target/x86_64_unknown_bitrig.rs
+++ b/src/librustc_back/target/x86_64_unknown_bitrig.rs
@@ -8,14 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::bitrig_base::opts();
+    base.cpu = "x86-64".to_string();
     base.max_atomic_width = 64;
     base.pre_link_args.push("-m64".to_string());
 
-    Target {
+    Ok(Target {
         llvm_target: "x86_64-unknown-bitrig".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
@@ -25,5 +26,5 @@
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
         options: base,
-    }
+    })
 }
diff --git a/src/librustc_back/target/x86_64_unknown_dragonfly.rs b/src/librustc_back/target/x86_64_unknown_dragonfly.rs
index 2535071..7e40d49 100644
--- a/src/librustc_back/target/x86_64_unknown_dragonfly.rs
+++ b/src/librustc_back/target/x86_64_unknown_dragonfly.rs
@@ -8,15 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::dragonfly_base::opts();
     base.cpu = "x86-64".to_string();
     base.max_atomic_width = 64;
     base.pre_link_args.push("-m64".to_string());
 
-    Target {
+    Ok(Target {
         llvm_target: "x86_64-unknown-dragonfly".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
@@ -26,5 +26,5 @@
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
         options: base,
-    }
+    })
 }
diff --git a/src/librustc_back/target/x86_64_unknown_freebsd.rs b/src/librustc_back/target/x86_64_unknown_freebsd.rs
index d3ad057..f38cdd4 100644
--- a/src/librustc_back/target/x86_64_unknown_freebsd.rs
+++ b/src/librustc_back/target/x86_64_unknown_freebsd.rs
@@ -8,15 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::freebsd_base::opts();
     base.cpu = "x86-64".to_string();
     base.max_atomic_width = 64;
     base.pre_link_args.push("-m64".to_string());
 
-    Target {
+    Ok(Target {
         llvm_target: "x86_64-unknown-freebsd".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
@@ -26,5 +26,5 @@
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
         options: base,
-    }
+    })
 }
diff --git a/src/librustc_back/target/x86_64_unknown_linux_gnu.rs b/src/librustc_back/target/x86_64_unknown_linux_gnu.rs
index 7908e0d..ef81d39 100644
--- a/src/librustc_back/target/x86_64_unknown_linux_gnu.rs
+++ b/src/librustc_back/target/x86_64_unknown_linux_gnu.rs
@@ -8,15 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
     base.cpu = "x86-64".to_string();
     base.max_atomic_width = 64;
     base.pre_link_args.push("-m64".to_string());
 
-    Target {
+    Ok(Target {
         llvm_target: "x86_64-unknown-linux-gnu".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
@@ -26,5 +26,5 @@
         target_env: "gnu".to_string(),
         target_vendor: "unknown".to_string(),
         options: base,
-    }
+    })
 }
diff --git a/src/librustc_back/target/x86_64_unknown_linux_musl.rs b/src/librustc_back/target/x86_64_unknown_linux_musl.rs
index 3301e0e..4bad775 100644
--- a/src/librustc_back/target/x86_64_unknown_linux_musl.rs
+++ b/src/librustc_back/target/x86_64_unknown_linux_musl.rs
@@ -8,15 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::linux_musl_base::opts();
     base.cpu = "x86-64".to_string();
     base.max_atomic_width = 64;
     base.pre_link_args.push("-m64".to_string());
 
-    Target {
+    Ok(Target {
         llvm_target: "x86_64-unknown-linux-musl".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
@@ -26,5 +26,5 @@
         target_env: "musl".to_string(),
         target_vendor: "unknown".to_string(),
         options: base,
-    }
+    })
 }
diff --git a/src/librustc_back/target/x86_64_unknown_netbsd.rs b/src/librustc_back/target/x86_64_unknown_netbsd.rs
index 7e6d1b7..2d0b1e2 100644
--- a/src/librustc_back/target/x86_64_unknown_netbsd.rs
+++ b/src/librustc_back/target/x86_64_unknown_netbsd.rs
@@ -8,14 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::netbsd_base::opts();
+    base.cpu = "x86-64".to_string();
     base.max_atomic_width = 64;
     base.pre_link_args.push("-m64".to_string());
 
-    Target {
+    Ok(Target {
         llvm_target: "x86_64-unknown-netbsd".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
@@ -25,5 +26,5 @@
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
         options: base,
-    }
+    })
 }
diff --git a/src/librustc_back/target/x86_64_unknown_openbsd.rs b/src/librustc_back/target/x86_64_unknown_openbsd.rs
index 823b099..339dbd5 100644
--- a/src/librustc_back/target/x86_64_unknown_openbsd.rs
+++ b/src/librustc_back/target/x86_64_unknown_openbsd.rs
@@ -8,15 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::Target;
+use target::{Target, TargetResult};
 
-pub fn target() -> Target {
+pub fn target() -> TargetResult {
     let mut base = super::openbsd_base::opts();
     base.cpu = "x86-64".to_string();
     base.max_atomic_width = 64;
     base.pre_link_args.push("-m64".to_string());
 
-    Target {
+    Ok(Target {
         llvm_target: "x86_64-unknown-openbsd".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
@@ -26,5 +26,5 @@
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
         options: base,
-    }
+    })
 }
diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs
index e86120b..1fe47cd 100644
--- a/src/librustc_borrowck/borrowck/mod.rs
+++ b/src/librustc_borrowck/borrowck/mod.rs
@@ -197,7 +197,7 @@
                              decl,
                              body);
 
-    intravisit::walk_fn(this, fk, decl, body, sp);
+    intravisit::walk_fn(this, fk, decl, body, sp, id);
 }
 
 fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>,
diff --git a/src/librustc_const_eval/Cargo.toml b/src/librustc_const_eval/Cargo.toml
index 01872bb..8967672 100644
--- a/src/librustc_const_eval/Cargo.toml
+++ b/src/librustc_const_eval/Cargo.toml
@@ -14,6 +14,7 @@
 rustc = { path = "../librustc" }
 rustc_back = { path = "../librustc_back" }
 rustc_const_math = { path = "../librustc_const_math" }
+rustc_errors = { path = "../librustc_errors" }
 syntax = { path = "../libsyntax" }
 graphviz = { path = "../libgraphviz" }
 syntax_pos = { path = "../libsyntax_pos" }
\ No newline at end of file
diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs
index 0de00d9..d3952de 100644
--- a/src/librustc_const_eval/check_match.rs
+++ b/src/librustc_const_eval/check_match.rs
@@ -17,6 +17,7 @@
 use ::{eval_const_expr, eval_const_expr_partial, compare_const_vals};
 use ::{const_expr_to_pat, lookup_const_by_id};
 use ::EvalHint::ExprTypeChecked;
+use eval::report_const_eval_err;
 use rustc::hir::def::*;
 use rustc::hir::def_id::{DefId};
 use rustc::middle::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor};
@@ -33,7 +34,7 @@
 
 use rustc::hir;
 use rustc::hir::{Pat, PatKind};
-use rustc::hir::intravisit::{self, IdVisitor, IdVisitingOperation, Visitor, FnKind};
+use rustc::hir::intravisit::{self, Visitor, FnKind};
 use rustc_back::slice;
 
 use syntax::ast::{self, DUMMY_NODE_ID, NodeId};
@@ -42,6 +43,7 @@
 use rustc::hir::fold::{Folder, noop_fold_pat};
 use rustc::hir::print::pat_to_string;
 use syntax::ptr::P;
+use rustc::util::common::ErrorReported;
 use rustc::util::nodemap::FnvHashMap;
 
 pub const DUMMY_WILD_PAT: &'static Pat = &Pat {
@@ -279,13 +281,7 @@
                 Ok(_) => {}
 
                 Err(err) => {
-                    let mut diag = struct_span_err!(cx.tcx.sess, err.span, E0471,
-                                                    "constant evaluation error: {}",
-                                                    err.description());
-                    if !p.span.contains(err.span) {
-                        diag.span_note(p.span, "in pattern here");
-                    }
-                    diag.emit();
+                    report_const_eval_err(cx.tcx, &err, p.span, "pattern").emit();
                 }
             }
         }
@@ -478,7 +474,7 @@
     renaming_map: &'map mut FnvHashMap<(NodeId, Span), NodeId>
 }
 
-impl<'map> IdVisitingOperation for RenamingRecorder<'map> {
+impl<'v, 'map> Visitor<'v> for RenamingRecorder<'map> {
     fn visit_id(&mut self, node_id: NodeId) {
         let key = (node_id, self.origin_span);
         self.renaming_map.insert(key, self.substituted_node_id);
@@ -533,9 +529,7 @@
                 renaming_map: renaming_map,
             };
 
-            let mut id_visitor = IdVisitor::new(&mut renaming_recorder);
-
-            id_visitor.visit_expr(const_expr);
+            renaming_recorder.visit_expr(const_expr);
         }
     }
 }
@@ -838,22 +832,19 @@
     }
 }
 
-fn range_covered_by_constructor(ctor: &Constructor,
-                                from: &ConstVal, to: &ConstVal) -> Option<bool> {
+fn range_covered_by_constructor(tcx: TyCtxt, span: Span,
+                                ctor: &Constructor,
+                                from: &ConstVal, to: &ConstVal)
+                                -> Result<bool, ErrorReported> {
     let (c_from, c_to) = match *ctor {
         ConstantValue(ref value)        => (value, value),
         ConstantRange(ref from, ref to) => (from, to),
-        Single                          => return Some(true),
+        Single                          => return Ok(true),
         _                               => bug!()
     };
-    let cmp_from = compare_const_vals(c_from, from);
-    let cmp_to = compare_const_vals(c_to, to);
-    match (cmp_from, cmp_to) {
-        (Some(cmp_from), Some(cmp_to)) => {
-            Some(cmp_from != Ordering::Less && cmp_to != Ordering::Greater)
-        }
-        _ => None
-    }
+    let cmp_from = compare_const_vals(tcx, span, c_from, from)?;
+    let cmp_to = compare_const_vals(tcx, span, c_to, to)?;
+    Ok(cmp_from != Ordering::Less && cmp_to != Ordering::Greater)
 }
 
 fn wrap_pat<'a, 'b, 'tcx>(cx: &MatchCheckCtxt<'b, 'tcx>,
@@ -965,13 +956,12 @@
                 Some(vec![(pat, Some(mt.ty))])
             } else {
                 let expr_value = eval_const_expr(cx.tcx, &expr);
-                match range_covered_by_constructor(constructor, &expr_value, &expr_value) {
-                    Some(true) => Some(vec![]),
-                    Some(false) => None,
-                    None => {
-                        span_err!(cx.tcx.sess, pat_span, E0298, "mismatched types between arms");
-                        None
-                    }
+                match range_covered_by_constructor(
+                    cx.tcx, expr.span, constructor, &expr_value, &expr_value
+                ) {
+                    Ok(true) => Some(vec![]),
+                    Ok(false) => None,
+                    Err(ErrorReported) => None,
                 }
             }
         }
@@ -979,13 +969,12 @@
         PatKind::Range(ref from, ref to) => {
             let from_value = eval_const_expr(cx.tcx, &from);
             let to_value = eval_const_expr(cx.tcx, &to);
-            match range_covered_by_constructor(constructor, &from_value, &to_value) {
-                Some(true) => Some(vec![]),
-                Some(false) => None,
-                None => {
-                    span_err!(cx.tcx.sess, pat_span, E0299, "mismatched types between arms");
-                    None
-                }
+            match range_covered_by_constructor(
+                cx.tcx, pat_span, constructor, &from_value, &to_value
+            ) {
+                Ok(true) => Some(vec![]),
+                Ok(false) => None,
+                Err(ErrorReported) => None,
             }
         }
 
@@ -1058,7 +1047,7 @@
         _ => cx.param_env = ParameterEnvironment::for_item(cx.tcx, fn_id),
     }
 
-    intravisit::walk_fn(cx, kind, decl, body, sp);
+    intravisit::walk_fn(cx, kind, decl, body, sp, fn_id);
 
     for input in &decl.inputs {
         check_irrefutable(cx, &input.pat, true);
diff --git a/src/librustc_const_eval/diagnostics.rs b/src/librustc_const_eval/diagnostics.rs
index f2abdf8..45414c3 100644
--- a/src/librustc_const_eval/diagnostics.rs
+++ b/src/librustc_const_eval/diagnostics.rs
@@ -551,6 +551,26 @@
 See also https://github.com/rust-lang/rust/issues/14587
 "##,
 
+E0080: r##"
+This error indicates that the compiler was unable to sensibly evaluate an
+constant expression that had to be evaluated. Attempting to divide by 0
+or causing integer overflow are two ways to induce this error. For example:
+
+```compile_fail
+enum Enum {
+    X = (1 << 500),
+    Y = (1 / 0)
+}
+```
+
+Ensure that the expressions given can be evaluated as the desired integer type.
+See the FFI section of the Reference for more information about using a custom
+integer type:
+
+https://doc.rust-lang.org/reference.html#ffi-attributes
+"##,
+
+
 E0306: r##"
 In an array literal `[x; N]`, `N` is the number of elements in the array. This
 must be an unsigned integer. Erroneous code example:
@@ -566,29 +586,11 @@
 let x = [0i32; 2];
 ```
 "##,
-
-E0307: r##"
-The length of an array is part of its type. For this reason, this length must
-be a compile-time constant. Erroneous code example:
-
-```compile_fail
-    let len = 10;
-    let x = [0i32; len]; // error: expected constant integer for repeat count,
-                         //        found variable
-```
-
-Working example:
-
-```
-let x = [0i32; 10];
-```
-"##,
-
 }
 
 
 register_diagnostics! {
-E0298, // mismatched types between arms
-E0299, // mismatched types between arms
-E0471, // constant evaluation error: ..
+    E0298, // cannot compare constants
+//  E0299, // mismatched types between arms
+//  E0471, // constant evaluation error (in pattern)
 }
diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs
index 4643686..d424b57 100644
--- a/src/librustc_const_eval/eval.rs
+++ b/src/librustc_const_eval/eval.rs
@@ -17,7 +17,7 @@
 
 use rustc::hir::map as ast_map;
 use rustc::hir::map::blocks::FnLikeNode;
-use rustc::middle::cstore::{self, InlinedItem};
+use rustc::middle::cstore::InlinedItem;
 use rustc::traits;
 use rustc::hir::def::{Def, PathResolution};
 use rustc::hir::def_id::DefId;
@@ -25,6 +25,7 @@
 use rustc::ty::{self, Ty, TyCtxt, subst};
 use rustc::ty::util::IntTypeExt;
 use rustc::traits::ProjectionMode;
+use rustc::util::common::ErrorReported;
 use rustc::util::nodemap::NodeMap;
 use rustc::lint;
 
@@ -43,6 +44,7 @@
 use std::collections::hash_map::Entry::Vacant;
 
 use rustc_const_math::*;
+use rustc_errors::{DiagnosticBuilder, check_old_school};
 
 macro_rules! math {
     ($e:expr, $op:expr) => {
@@ -140,13 +142,13 @@
         }
         let mut used_substs = false;
         let expr_ty = match tcx.sess.cstore.maybe_get_item_ast(tcx, def_id) {
-            cstore::FoundAst::Found(&InlinedItem::Item(ref item)) => match item.node {
+            Some((&InlinedItem::Item(ref item), _)) => match item.node {
                 hir::ItemConst(ref ty, ref const_expr) => {
                     Some((&**const_expr, tcx.ast_ty_to_prim_ty(ty)))
                 },
                 _ => None
             },
-            cstore::FoundAst::Found(&InlinedItem::TraitItem(trait_id, ref ti)) => match ti.node {
+            Some((&InlinedItem::TraitItem(trait_id, ref ti), _)) => match ti.node {
                 hir::ConstTraitItem(_, _) => {
                     used_substs = true;
                     if let Some(substs) = substs {
@@ -161,7 +163,7 @@
                 }
                 _ => None
             },
-            cstore::FoundAst::Found(&InlinedItem::ImplItem(_, ref ii)) => match ii.node {
+            Some((&InlinedItem::ImplItem(_, ref ii), _)) => match ii.node {
                 hir::ImplItemKind::Const(ref ty, ref expr) => {
                     Some((&**expr, tcx.ast_ty_to_prim_ty(ty)))
                 },
@@ -196,8 +198,8 @@
     }
 
     let fn_id = match tcx.sess.cstore.maybe_get_item_ast(tcx, def_id) {
-        cstore::FoundAst::Found(&InlinedItem::Item(ref item)) => Some(item.id),
-        cstore::FoundAst::Found(&InlinedItem::ImplItem(_, ref item)) => Some(item.id),
+        Some((&InlinedItem::Item(ref item), _)) => Some(item.id),
+        Some((&InlinedItem::ImplItem(_, ref item), _)) => Some(item.id),
         _ => None
     };
     tcx.extern_const_fns.borrow_mut().insert(def_id,
@@ -338,20 +340,71 @@
     Ok(P(hir::Pat { id: expr.id, node: pat, span: span }))
 }
 
+pub fn report_const_eval_err<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    err: &ConstEvalErr,
+    primary_span: Span,
+    primary_kind: &str)
+    -> DiagnosticBuilder<'tcx>
+{
+    let mut err = err;
+    while let &ConstEvalErr { kind: ErroneousReferencedConstant(box ref i_err), .. } = err {
+        err = i_err;
+    }
+
+    let mut diag = struct_span_err!(tcx.sess, err.span, E0080, "constant evaluation error");
+    note_const_eval_err(tcx, err, primary_span, primary_kind, &mut diag);
+    diag
+}
+
+pub fn fatal_const_eval_err<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    err: &ConstEvalErr,
+    primary_span: Span,
+    primary_kind: &str)
+    -> !
+{
+    report_const_eval_err(tcx, err, primary_span, primary_kind).emit();
+    tcx.sess.abort_if_errors();
+    unreachable!()
+}
+
+pub fn note_const_eval_err<'a, 'tcx>(
+    _tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    err: &ConstEvalErr,
+    primary_span: Span,
+    primary_kind: &str,
+    diag: &mut DiagnosticBuilder)
+{
+    match err.description() {
+        ConstEvalErrDescription::Simple(message) => {
+            if check_old_school() {
+                diag.note(&message);
+            } else {
+                diag.span_label(err.span, &message);
+            }
+        }
+    }
+
+    if !primary_span.contains(err.span) {
+        diag.span_note(primary_span,
+                       &format!("for {} here", primary_kind));
+    }
+}
+
 pub fn eval_const_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                  e: &Expr) -> ConstVal {
     match eval_const_expr_partial(tcx, e, ExprTypeChecked, None) {
         Ok(r) => r,
         // non-const path still needs to be a fatal error, because enums are funky
         Err(s) => {
+            report_const_eval_err(tcx, &s, e.span, "expression").emit();
             match s.kind {
                 NonConstPath |
-                UnimplementedConstVal(_) => tcx.sess.span_fatal(s.span, &s.description()),
-                _ => {
-                    tcx.sess.span_err(s.span, &s.description());
-                    Dummy
-                }
+                UnimplementedConstVal(_) => tcx.sess.abort_if_errors(),
+                _ => {}
             }
+            Dummy
         },
     }
 }
@@ -400,6 +453,7 @@
     IntermediateUnsignedNegative,
     /// Expected, Got
     TypeMismatch(String, ConstInt),
+
     BadType(ConstVal),
     ErroneousReferencedConstant(Box<ConstEvalErr>),
     CharCast(ConstInt),
@@ -411,57 +465,79 @@
     }
 }
 
+#[derive(Clone, Debug)]
+pub enum ConstEvalErrDescription<'a> {
+    Simple(Cow<'a, str>),
+}
+
+impl<'a> ConstEvalErrDescription<'a> {
+    /// Return a one-line description of the error, for lints and such
+    pub fn into_oneline(self) -> Cow<'a, str> {
+        match self {
+            ConstEvalErrDescription::Simple(simple) => simple,
+        }
+    }
+}
+
 impl ConstEvalErr {
-    pub fn description(&self) -> Cow<str> {
+    pub fn description(&self) -> ConstEvalErrDescription {
         use self::ErrKind::*;
+        use self::ConstEvalErrDescription::*;
+
+        macro_rules! simple {
+            ($msg:expr) => ({ Simple($msg.into_cow()) });
+            ($fmt:expr, $($arg:tt)+) => ({
+                Simple(format!($fmt, $($arg)+).into_cow())
+            })
+        }
 
         match self.kind {
-            CannotCast => "can't cast this type".into_cow(),
-            CannotCastTo(s) => format!("can't cast this type to {}", s).into_cow(),
-            InvalidOpForInts(_) =>  "can't do this op on integrals".into_cow(),
-            InvalidOpForBools(_) =>  "can't do this op on bools".into_cow(),
-            InvalidOpForFloats(_) => "can't do this op on floats".into_cow(),
-            InvalidOpForIntUint(..) => "can't do this op on an isize and usize".into_cow(),
-            InvalidOpForUintInt(..) => "can't do this op on a usize and isize".into_cow(),
-            NegateOn(ref const_val) => format!("negate on {}", const_val.description()).into_cow(),
-            NotOn(ref const_val) => format!("not on {}", const_val.description()).into_cow(),
-            CallOn(ref const_val) => format!("call on {}", const_val.description()).into_cow(),
+            CannotCast => simple!("can't cast this type"),
+            CannotCastTo(s) => simple!("can't cast this type to {}", s),
+            InvalidOpForInts(_) =>  simple!("can't do this op on integrals"),
+            InvalidOpForBools(_) =>  simple!("can't do this op on bools"),
+            InvalidOpForFloats(_) => simple!("can't do this op on floats"),
+            InvalidOpForIntUint(..) => simple!("can't do this op on an isize and usize"),
+            InvalidOpForUintInt(..) => simple!("can't do this op on a usize and isize"),
+            NegateOn(ref const_val) => simple!("negate on {}", const_val.description()),
+            NotOn(ref const_val) => simple!("not on {}", const_val.description()),
+            CallOn(ref const_val) => simple!("call on {}", const_val.description()),
 
-            MissingStructField  => "nonexistent struct field".into_cow(),
-            NonConstPath        => "non-constant path in constant expression".into_cow(),
+            MissingStructField  => simple!("nonexistent struct field"),
+            NonConstPath        => simple!("non-constant path in constant expression"),
             UnimplementedConstVal(what) =>
-                format!("unimplemented constant expression: {}", what).into_cow(),
-            UnresolvedPath => "unresolved path in constant expression".into_cow(),
-            ExpectedConstTuple => "expected constant tuple".into_cow(),
-            ExpectedConstStruct => "expected constant struct".into_cow(),
-            TupleIndexOutOfBounds => "tuple index out of bounds".into_cow(),
-            IndexedNonVec => "indexing is only supported for arrays".into_cow(),
-            IndexNegative => "indices must be non-negative integers".into_cow(),
-            IndexNotInt => "indices must be integers".into_cow(),
+                simple!("unimplemented constant expression: {}", what),
+            UnresolvedPath => simple!("unresolved path in constant expression"),
+            ExpectedConstTuple => simple!("expected constant tuple"),
+            ExpectedConstStruct => simple!("expected constant struct"),
+            TupleIndexOutOfBounds => simple!("tuple index out of bounds"),
+            IndexedNonVec => simple!("indexing is only supported for arrays"),
+            IndexNegative => simple!("indices must be non-negative integers"),
+            IndexNotInt => simple!("indices must be integers"),
             IndexOutOfBounds { len, index } => {
-                format!("index out of bounds: the len is {} but the index is {}",
-                        len, index).into_cow()
+                simple!("index out of bounds: the len is {} but the index is {}",
+                        len, index)
             }
-            RepeatCountNotNatural => "repeat count must be a natural number".into_cow(),
-            RepeatCountNotInt => "repeat count must be integers".into_cow(),
+            RepeatCountNotNatural => simple!("repeat count must be a natural number"),
+            RepeatCountNotInt => simple!("repeat count must be integers"),
 
-            MiscBinaryOp => "bad operands for binary".into_cow(),
-            MiscCatchAll => "unsupported constant expr".into_cow(),
-            IndexOpFeatureGated => "the index operation on const values is unstable".into_cow(),
-            Math(ref err) => err.description().into_cow(),
+            MiscBinaryOp => simple!("bad operands for binary"),
+            MiscCatchAll => simple!("unsupported constant expr"),
+            IndexOpFeatureGated => simple!("the index operation on const values is unstable"),
+            Math(ref err) => Simple(err.description().into_cow()),
 
-            IntermediateUnsignedNegative => "during the computation of an unsigned a negative \
-                                             number was encountered. This is most likely a bug in\
-                                             the constant evaluator".into_cow(),
+            IntermediateUnsignedNegative => simple!(
+                "during the computation of an unsigned a negative \
+                 number was encountered. This is most likely a bug in\
+                 the constant evaluator"),
 
             TypeMismatch(ref expected, ref got) => {
-                format!("mismatched types: expected `{}`, found `{}`",
-                        expected, got.description()).into_cow()
+                simple!("expected {}, found {}", expected, got.description())
             },
-            BadType(ref i) => format!("value of wrong type: {:?}", i).into_cow(),
-            ErroneousReferencedConstant(_) => "could not evaluate referenced constant".into_cow(),
+            BadType(ref i) => simple!("value of wrong type: {:?}", i),
+            ErroneousReferencedConstant(_) => simple!("could not evaluate referenced constant"),
             CharCast(ref got) => {
-                format!("only `u8` can be cast as `char`, not `{}`", got.description()).into_cow()
+                simple!("only `u8` can be cast as `char`, not `{}`", got.description())
             },
         }
     }
@@ -1199,8 +1275,10 @@
     })
 }
 
-pub fn compare_const_vals(a: &ConstVal, b: &ConstVal) -> Option<Ordering> {
-    match (a, b) {
+pub fn compare_const_vals(tcx: TyCtxt, span: Span, a: &ConstVal, b: &ConstVal)
+                          -> Result<Ordering, ErrorReported>
+{
+    let result = match (a, b) {
         (&Integral(a), &Integral(b)) => a.try_cmp(b).ok(),
         (&Float(a), &Float(b)) => a.try_cmp(b).ok(),
         (&Str(ref a), &Str(ref b)) => Some(a.cmp(b)),
@@ -1208,62 +1286,82 @@
         (&ByteStr(ref a), &ByteStr(ref b)) => Some(a.cmp(b)),
         (&Char(a), &Char(ref b)) => Some(a.cmp(b)),
         _ => None,
+    };
+
+    match result {
+        Some(result) => Ok(result),
+        None => {
+            // FIXME: can this ever be reached?
+            span_err!(tcx.sess, span, E0298,
+                      "type mismatch comparing {} and {}",
+                      a.description(),
+                      b.description());
+            Err(ErrorReported)
+        }
     }
 }
 
 pub fn compare_lit_exprs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                   span: Span,
                                    a: &Expr,
-                                   b: &Expr) -> Option<Ordering> {
+                                   b: &Expr) -> Result<Ordering, ErrorReported> {
     let a = match eval_const_expr_partial(tcx, a, ExprTypeChecked, None) {
         Ok(a) => a,
         Err(e) => {
-            tcx.sess.span_err(a.span, &e.description());
-            return None;
+            report_const_eval_err(tcx, &e, a.span, "expression").emit();
+            return Err(ErrorReported);
         }
     };
     let b = match eval_const_expr_partial(tcx, b, ExprTypeChecked, None) {
         Ok(b) => b,
         Err(e) => {
-            tcx.sess.span_err(b.span, &e.description());
-            return None;
+            report_const_eval_err(tcx, &e, b.span, "expression").emit();
+            return Err(ErrorReported);
         }
     };
-    compare_const_vals(&a, &b)
+    compare_const_vals(tcx, span, &a, &b)
 }
 
 
-/// Returns the repeat count for a repeating vector expression.
-pub fn eval_repeat_count<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                   count_expr: &hir::Expr) -> usize {
+/// Returns the value of the length-valued expression
+pub fn eval_length<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                             count_expr: &hir::Expr,
+                             reason: &str)
+                             -> Result<usize, ErrorReported>
+{
     let hint = UncheckedExprHint(tcx.types.usize);
     match eval_const_expr_partial(tcx, count_expr, hint, None) {
         Ok(Integral(Usize(count))) => {
             let val = count.as_u64(tcx.sess.target.uint_type);
             assert_eq!(val as usize as u64, val);
-            val as usize
+            Ok(val as usize)
         },
         Ok(const_val) => {
             span_err!(tcx.sess, count_expr.span, E0306,
-                      "expected positive integer for repeat count, found {}",
+                      "expected usize for {}, found {}",
+                      reason,
                       const_val.description());
-            0
+            Err(ErrorReported)
         }
         Err(err) => {
-            let err_msg = match count_expr.node {
+            let mut diag = report_const_eval_err(
+                tcx, &err, count_expr.span, reason);
+
+            match count_expr.node {
                 hir::ExprPath(None, hir::Path {
                     global: false,
                     ref segments,
                     ..
-                }) if segments.len() == 1 =>
-                    format!("found variable"),
-                _ => match err.kind {
-                    MiscCatchAll => format!("but found {}", err.description()),
-                    _ => format!("but {}", err.description())
+                }) if segments.len() == 1 => {
+                    if let Some(Def::Local(..)) = tcx.expect_def_or_none(count_expr.id) {
+                        diag.note(&format!("`{}` is a variable", segments[0].name));
+                    }
                 }
-            };
-            span_err!(tcx.sess, count_expr.span, E0307,
-                "expected constant integer for repeat count, {}", err_msg);
-            0
+                _ => {}
+            }
+
+            diag.emit();
+            Err(ErrorReported)
         }
     }
 }
diff --git a/src/librustc_const_eval/lib.rs b/src/librustc_const_eval/lib.rs
index 726ba4f..a6714c1 100644
--- a/src/librustc_const_eval/lib.rs
+++ b/src/librustc_const_eval/lib.rs
@@ -36,6 +36,7 @@
 #[macro_use] extern crate rustc;
 extern crate rustc_back;
 extern crate rustc_const_math;
+extern crate rustc_errors;
 extern crate graphviz;
 extern crate syntax_pos;
 extern crate serialize as rustc_serialize; // used by deriving
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index 657fc6c..f1f5e19 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -88,7 +88,7 @@
     // We need nested scopes here, because the intermediate results can keep
     // large chunks of memory alive and we want to free them as soon as
     // possible to keep the peak memory usage low
-    let (outputs, trans) = {
+    let (outputs, trans, crate_name) = {
         let krate = match phase_1_parse_input(sess, cfg, input) {
             Ok(krate) => krate,
             Err(mut parse_error) => {
@@ -113,13 +113,13 @@
         };
 
         let outputs = build_output_filenames(input, outdir, output, &krate.attrs, sess);
-        let id = link::find_crate_name(Some(sess), &krate.attrs, input);
+        let crate_name = link::find_crate_name(Some(sess), &krate.attrs, input);
         let ExpansionResult { expanded_crate, defs, analysis, resolutions, mut hir_forest } = {
             phase_2_configure_and_expand(
-                sess, &cstore, krate, &id, addl_plugins, control.make_glob_map,
+                sess, &cstore, krate, &crate_name, addl_plugins, control.make_glob_map,
                 |expanded_crate| {
                     let mut state = CompileState::state_after_expand(
-                        input, sess, outdir, output, &cstore, expanded_crate, &id,
+                        input, sess, outdir, output, &cstore, expanded_crate, &crate_name,
                     );
                     controller_entry_point!(after_expand, sess, state, Ok(()));
                     Ok(())
@@ -127,7 +127,7 @@
             )?
         };
 
-        write_out_deps(sess, &outputs, &id);
+        write_out_deps(sess, &outputs, &crate_name);
 
         let arenas = ty::CtxtArenas::new();
 
@@ -151,7 +151,7 @@
                                                                   &resolutions,
                                                                   &expanded_crate,
                                                                   &hir_map.krate(),
-                                                                  &id),
+                                                                  &crate_name),
                                     Ok(()));
         }
 
@@ -171,7 +171,7 @@
                                     analysis,
                                     resolutions,
                                     &arenas,
-                                    &id,
+                                    &crate_name,
                                     |tcx, mir_map, analysis, result| {
             {
                 // Eventually, we will want to track plugins.
@@ -186,7 +186,7 @@
                                                                    &analysis,
                                                                    mir_map.as_ref(),
                                                                    tcx,
-                                                                   &id);
+                                                                   &crate_name);
                 (control.after_analysis.callback)(&mut state);
 
                 if control.after_analysis.stop == Compilation::Stop {
@@ -212,11 +212,11 @@
             // Discard interned strings as they are no longer required.
             token::clear_ident_interner();
 
-            Ok((outputs, trans))
+            Ok((outputs, trans, crate_name.clone()))
         })??
     };
 
-    let phase5_result = phase_5_run_llvm_passes(sess, &trans, &outputs);
+    let phase5_result = phase_5_run_llvm_passes(sess, &crate_name, &trans, &outputs);
 
     controller_entry_point!(after_llvm,
                             sess,
@@ -566,7 +566,8 @@
     });
 
     *sess.crate_types.borrow_mut() = collect_crate_types(sess, &krate.attrs);
-    sess.crate_disambiguator.set(token::intern(&compute_crate_disambiguator(sess)));
+    *sess.crate_disambiguator.borrow_mut() =
+        token::intern(&compute_crate_disambiguator(sess)).as_str();
 
     time(time_passes, "recursion limit", || {
         middle::recursion_limit::update_recursion_limit(sess, &krate);
@@ -1021,6 +1022,7 @@
 /// Run LLVM itself, producing a bitcode file, assembly file or object file
 /// as a side effect.
 pub fn phase_5_run_llvm_passes(sess: &Session,
+                               crate_name: &str,
                                trans: &trans::CrateTranslation,
                                outputs: &OutputFilenames) -> CompileResult {
     if sess.opts.cg.no_integrated_as {
@@ -1042,6 +1044,10 @@
              || write::run_passes(sess, trans, &sess.opts.output_types, outputs));
     }
 
+    time(sess.time_passes(),
+         "serialize work products",
+         move || rustc_incremental::save_work_products(sess, crate_name));
+
     if sess.err_count() > 0 {
         Err(sess.err_count())
     } else {
@@ -1065,14 +1071,14 @@
     filename.replace(" ", "\\ ")
 }
 
-fn write_out_deps(sess: &Session, outputs: &OutputFilenames, id: &str) {
+fn write_out_deps(sess: &Session, outputs: &OutputFilenames, crate_name: &str) {
     let mut out_filenames = Vec::new();
     for output_type in sess.opts.output_types.keys() {
         let file = outputs.path(*output_type);
         match *output_type {
             OutputType::Exe => {
                 for output in sess.crate_types.borrow().iter() {
-                    let p = link::filename_for_input(sess, *output, id, outputs);
+                    let p = link::filename_for_input(sess, *output, crate_name, outputs);
                     out_filenames.push(p);
                 }
             }
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 0a8df92..772c59b 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -31,7 +31,6 @@
 #![feature(set_stdio)]
 #![feature(staged_api)]
 #![feature(question_mark)]
-#![feature(unboxed_closures)]
 
 extern crate arena;
 extern crate flate;
@@ -95,6 +94,7 @@
 use rustc::session::early_error;
 
 use syntax::{ast, json};
+use syntax::attr::AttrMetaMethods;
 use syntax::codemap::{CodeMap, FileLoader, RealFileLoader};
 use syntax::feature_gate::{GatedCfg, UnstableFeatures};
 use syntax::parse::{self, PResult};
@@ -186,7 +186,7 @@
     let sopts = config::build_session_options(&matches);
 
     if sopts.debugging_opts.debug_llvm {
-        unsafe { llvm::LLVMSetDebug(1); }
+        unsafe { llvm::LLVMRustSetDebug(1); }
     }
 
     let descriptions = diagnostics_registry();
@@ -392,15 +392,12 @@
 
     let mut saw_invalid_predicate = false;
     for item in sopts.cfg.iter() {
-        match item.node {
-            ast::MetaItemKind::List(ref pred, _) => {
-                saw_invalid_predicate = true;
-                handler.emit(&MultiSpan::new(),
-                             &format!("invalid predicate in --cfg command line argument: `{}`",
-                                      pred),
-                                errors::Level::Fatal);
-            }
-            _ => {},
+        if item.is_meta_item_list() {
+            saw_invalid_predicate = true;
+            handler.emit(&MultiSpan::new(),
+                         &format!("invalid predicate in --cfg command line argument: `{}`",
+                                  item.name()),
+                            errors::Level::Fatal);
         }
     }
 
@@ -609,7 +606,7 @@
         for req in &sess.opts.prints {
             match *req {
                 PrintRequest::TargetList => {
-                    let mut targets = rustc_back::target::TARGETS.to_vec();
+                    let mut targets = rustc_back::target::get_targets().collect::<Vec<String>>();
                     targets.sort();
                     println!("{}", targets.join("\n"));
                 },
@@ -649,20 +646,17 @@
                         if !allow_unstable_cfg && GatedCfg::gate(&*cfg).is_some() {
                             continue;
                         }
-                        match cfg.node {
-                            ast::MetaItemKind::Word(ref word) => println!("{}", word),
-                            ast::MetaItemKind::NameValue(ref name, ref value) => {
-                                println!("{}=\"{}\"", name, match value.node {
-                                    ast::LitKind::Str(ref s, _) => s,
-                                    _ => continue,
-                                });
+                        if cfg.is_word() {
+                            println!("{}", cfg.name());
+                        } else if cfg.is_value_str() {
+                            if let Some(s) = cfg.value_str() {
+                                println!("{}=\"{}\"", cfg.name(), s);
                             }
+                        } else if cfg.is_meta_item_list() {
                             // Right now there are not and should not be any
                             // MetaItemKind::List items in the configuration returned by
                             // `build_configuration`.
-                            ast::MetaItemKind::List(..) => {
-                                panic!("MetaItemKind::List encountered in default cfg")
-                            }
+                            panic!("MetaItemKind::List encountered in default cfg")
                         }
                     }
                 }
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index 6a48f65..610e564 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -531,10 +531,12 @@
         DiagnosticBuilder::new(self, Level::Fatal, msg)
     }
 
-    pub fn cancel(&mut self, err: &mut DiagnosticBuilder) {
+    pub fn cancel(&self, err: &mut DiagnosticBuilder) {
         if err.level == Level::Error || err.level == Level::Fatal {
-            assert!(self.has_errors());
-            self.err_count.set(self.err_count.get() + 1);
+            self.err_count.set(
+                self.err_count.get().checked_sub(1)
+                    .expect("cancelled an error but err_count is 0")
+            );
         }
         err.cancel();
     }
diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs
index d38f979..774c5ca 100644
--- a/src/librustc_incremental/assert_dep_graph.rs
+++ b/src/librustc_incremental/assert_dep_graph.rs
@@ -110,13 +110,11 @@
             if attr.check_name(IF_THIS_CHANGED) {
                 let mut id = None;
                 for meta_item in attr.meta_item_list().unwrap_or_default() {
-                    match meta_item.node {
-                        ast::MetaItemKind::Word(ref s) if id.is_none() => id = Some(s.clone()),
-                        _ => {
-                            self.tcx.sess.span_err(
-                                meta_item.span,
-                                &format!("unexpected meta-item {:?}", meta_item.node));
-                        }
+                    if meta_item.is_word() && id.is_none() {
+                        id = Some(meta_item.name().clone());
+                    } else {
+                        // FIXME better-encapsulate meta_item (don't directly access `node`)
+                        span_bug!(meta_item.span(), "unexpected meta-item {:?}", meta_item.node)
                     }
                 }
                 let id = id.unwrap_or(InternedString::new(ID));
@@ -127,16 +125,13 @@
                 let mut dep_node_interned = None;
                 let mut id = None;
                 for meta_item in attr.meta_item_list().unwrap_or_default() {
-                    match meta_item.node {
-                        ast::MetaItemKind::Word(ref s) if dep_node_interned.is_none() =>
-                            dep_node_interned = Some(s.clone()),
-                        ast::MetaItemKind::Word(ref s) if id.is_none() =>
-                            id = Some(s.clone()),
-                        _ => {
-                            self.tcx.sess.span_err(
-                                meta_item.span,
-                                &format!("unexpected meta-item {:?}", meta_item.node));
-                        }
+                    if meta_item.is_word() && dep_node_interned.is_none() {
+                        dep_node_interned = Some(meta_item.name().clone());
+                    } else if meta_item.is_word() && id.is_none() {
+                        id = Some(meta_item.name().clone());
+                    } else {
+                        // FIXME better-encapsulate meta_item (don't directly access `node`)
+                        span_bug!(meta_item.span(), "unexpected meta-item {:?}", meta_item.node)
                     }
                 }
                 let dep_node = match dep_node_interned {
diff --git a/src/librustc_incremental/calculate_svh.rs b/src/librustc_incremental/calculate_svh.rs
index cbc246a..bea6b7e 100644
--- a/src/librustc_incremental/calculate_svh.rs
+++ b/src/librustc_incremental/calculate_svh.rs
@@ -11,6 +11,7 @@
 //! Calculation of a Strict Version Hash for crates.  For a length
 //! comment explaining the general idea, see `librustc/middle/svh.rs`.
 
+use syntax::attr::AttributeMethods;
 use std::hash::{Hash, SipHasher, Hasher};
 use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
 use rustc::hir::svh::Svh;
@@ -36,7 +37,7 @@
         // to ensure it is not incorporating implementation artifacts into
         // the hash that are not otherwise visible.)
 
-        let crate_disambiguator = self.sess.crate_disambiguator.get();
+        let crate_disambiguator = self.sess.local_crate_disambiguator();
         let krate = self.map.krate();
 
         // FIXME: this should use SHA1, not SipHash. SipHash is not built to
@@ -47,10 +48,10 @@
         // FIXME(#32753) -- at (*) we `to_le` for endianness, but is
         // this enough, and does it matter anyway?
         "crate_disambiguator".hash(&mut state);
-        crate_disambiguator.as_str().len().to_le().hash(&mut state); // (*)
-        crate_disambiguator.as_str().hash(&mut state);
+        crate_disambiguator.len().to_le().hash(&mut state); // (*)
+        crate_disambiguator.hash(&mut state);
 
-        debug!("crate_disambiguator: {:?}", crate_disambiguator.as_str());
+        debug!("crate_disambiguator: {:?}", crate_disambiguator);
         debug!("state: {:?}", state);
 
         {
@@ -69,7 +70,7 @@
         // to avoid hashing the AttrId
         for attr in &krate.attrs {
             debug!("krate attr {:?}", attr);
-            attr.node.value.hash(&mut state);
+            attr.meta().hash(&mut state);
         }
 
         Svh::new(state.finish())
@@ -119,6 +120,7 @@
     use rustc::ty::TyCtxt;
     use rustc::hir;
     use rustc::hir::*;
+    use rustc::hir::map::DefPath;
     use rustc::hir::intravisit as visit;
     use rustc::hir::intravisit::{Visitor, FnKind};
 
@@ -135,6 +137,15 @@
                    -> Self {
             StrictVersionHashVisitor { st: st, tcx: tcx }
         }
+
+        fn hash_def_path(&mut self, path: &DefPath) {
+            self.tcx.crate_name(path.krate).hash(self.st);
+            self.tcx.crate_disambiguator(path.krate).hash(self.st);
+            for data in &path.data {
+                data.data.as_interned_str().hash(self.st);
+                data.disambiguator.hash(self.st);
+            }
+        }
     }
 
     // To off-load the bulk of the hash-computation on #[derive(Hash)],
@@ -289,19 +300,21 @@
 
     impl<'a, 'tcx> Visitor<'a> for StrictVersionHashVisitor<'a, 'tcx> {
         fn visit_nested_item(&mut self, item: ItemId) {
-            debug!("visit_nested_item: {:?} st={:?}", item, self.st);
-            let def_path = self.tcx.map.def_path_from_id(item.id);
-            def_path.hash(self.st);
+            let def_path = self.tcx.map.def_path_from_id(item.id).unwrap();
+            debug!("visit_nested_item: def_path={:?} st={:?}", def_path, self.st);
+            self.hash_def_path(&def_path);
         }
 
         fn visit_variant_data(&mut self, s: &'a VariantData, name: Name,
                               g: &'a Generics, _: NodeId, _: Span) {
+            debug!("visit_variant_data: st={:?}", self.st);
             SawStructDef(name.as_str()).hash(self.st);
             visit::walk_generics(self, g);
             visit::walk_struct_def(self, s)
         }
 
         fn visit_variant(&mut self, v: &'a Variant, g: &'a Generics, item_id: NodeId) {
+            debug!("visit_variant: st={:?}", self.st);
             SawVariant.hash(self.st);
             // walk_variant does not call walk_generics, so do it here.
             visit::walk_generics(self, g);
@@ -323,14 +336,17 @@
         // pattern, please move that method up above this comment.)
 
         fn visit_name(&mut self, _: Span, name: Name) {
+            debug!("visit_name: st={:?}", self.st);
             SawIdent(name.as_str()).hash(self.st);
         }
 
         fn visit_lifetime(&mut self, l: &'a Lifetime) {
+            debug!("visit_lifetime: st={:?}", self.st);
             SawLifetime(l.name.as_str()).hash(self.st);
         }
 
         fn visit_lifetime_def(&mut self, l: &'a LifetimeDef) {
+            debug!("visit_lifetime_def: st={:?}", self.st);
             SawLifetimeDef(l.lifetime.name.as_str()).hash(self.st);
         }
 
@@ -340,14 +356,18 @@
         // that a change to a crate body will require downstream
         // crates to be recompiled.
         fn visit_expr(&mut self, ex: &'a Expr) {
+            debug!("visit_expr: st={:?}", self.st);
             SawExpr(saw_expr(&ex.node)).hash(self.st); visit::walk_expr(self, ex)
         }
 
         fn visit_stmt(&mut self, s: &'a Stmt) {
+            debug!("visit_stmt: st={:?}", self.st);
             SawStmt(saw_stmt(&s.node)).hash(self.st); visit::walk_stmt(self, s)
         }
 
         fn visit_foreign_item(&mut self, i: &'a ForeignItem) {
+            debug!("visit_foreign_item: st={:?}", self.st);
+
             // FIXME (#14132) ideally we would incorporate privacy (or
             // perhaps reachability) somewhere here, so foreign items
             // that do not leak into downstream crates would not be
@@ -357,6 +377,7 @@
 
         fn visit_item(&mut self, i: &'a Item) {
             debug!("visit_item: {:?} st={:?}", i, self.st);
+
             // FIXME (#14132) ideally would incorporate reachability
             // analysis somewhere here, so items that never leak into
             // downstream crates (e.g. via monomorphisation or
@@ -364,56 +385,69 @@
             SawItem.hash(self.st); visit::walk_item(self, i)
         }
 
-        fn visit_mod(&mut self, m: &'a Mod, _s: Span, _n: NodeId) {
-            SawMod.hash(self.st); visit::walk_mod(self, m)
+        fn visit_mod(&mut self, m: &'a Mod, _s: Span, n: NodeId) {
+            debug!("visit_mod: st={:?}", self.st);
+            SawMod.hash(self.st); visit::walk_mod(self, m, n)
         }
 
         fn visit_decl(&mut self, d: &'a Decl) {
+            debug!("visit_decl: st={:?}", self.st);
             SawDecl.hash(self.st); visit::walk_decl(self, d)
         }
 
         fn visit_ty(&mut self, t: &'a Ty) {
+            debug!("visit_ty: st={:?}", self.st);
             SawTy.hash(self.st); visit::walk_ty(self, t)
         }
 
         fn visit_generics(&mut self, g: &'a Generics) {
+            debug!("visit_generics: st={:?}", self.st);
             SawGenerics.hash(self.st); visit::walk_generics(self, g)
         }
 
         fn visit_fn(&mut self, fk: FnKind<'a>, fd: &'a FnDecl,
-                    b: &'a Block, s: Span, _: NodeId) {
-            SawFn.hash(self.st); visit::walk_fn(self, fk, fd, b, s)
+                    b: &'a Block, s: Span, n: NodeId) {
+            debug!("visit_fn: st={:?}", self.st);
+            SawFn.hash(self.st); visit::walk_fn(self, fk, fd, b, s, n)
         }
 
         fn visit_trait_item(&mut self, ti: &'a TraitItem) {
+            debug!("visit_trait_item: st={:?}", self.st);
             SawTraitItem.hash(self.st); visit::walk_trait_item(self, ti)
         }
 
         fn visit_impl_item(&mut self, ii: &'a ImplItem) {
+            debug!("visit_impl_item: st={:?}", self.st);
             SawImplItem.hash(self.st); visit::walk_impl_item(self, ii)
         }
 
         fn visit_struct_field(&mut self, s: &'a StructField) {
+            debug!("visit_struct_field: st={:?}", self.st);
             SawStructField.hash(self.st); visit::walk_struct_field(self, s)
         }
 
         fn visit_path(&mut self, path: &'a Path, _: ast::NodeId) {
+            debug!("visit_path: st={:?}", self.st);
             SawPath.hash(self.st); visit::walk_path(self, path)
         }
 
         fn visit_block(&mut self, b: &'a Block) {
+            debug!("visit_block: st={:?}", self.st);
             SawBlock.hash(self.st); visit::walk_block(self, b)
         }
 
         fn visit_pat(&mut self, p: &'a Pat) {
+            debug!("visit_pat: st={:?}", self.st);
             SawPat.hash(self.st); visit::walk_pat(self, p)
         }
 
         fn visit_local(&mut self, l: &'a Local) {
+            debug!("visit_local: st={:?}", self.st);
             SawLocal.hash(self.st); visit::walk_local(self, l)
         }
 
         fn visit_arm(&mut self, a: &'a Arm) {
+            debug!("visit_arm: st={:?}", self.st);
             SawArm.hash(self.st); visit::walk_arm(self, a)
         }
     }
diff --git a/src/librustc_incremental/lib.rs b/src/librustc_incremental/lib.rs
index ed31e0b..0d11b07 100644
--- a/src/librustc_incremental/lib.rs
+++ b/src/librustc_incremental/lib.rs
@@ -19,6 +19,7 @@
       html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![cfg_attr(not(stage0), deny(warnings))]
 
+#![feature(question_mark)]
 #![feature(rustc_private)]
 #![feature(staged_api)]
 
@@ -40,3 +41,6 @@
 pub use calculate_svh::SvhCalculate;
 pub use persist::load_dep_graph;
 pub use persist::save_dep_graph;
+pub use persist::save_trans_partition;
+pub use persist::save_work_products;
+pub use persist::in_incr_comp_dir;
diff --git a/src/librustc_incremental/persist/data.rs b/src/librustc_incremental/persist/data.rs
index f57ab19..95e9a16 100644
--- a/src/librustc_incremental/persist/data.rs
+++ b/src/librustc_incremental/persist/data.rs
@@ -10,8 +10,9 @@
 
 //! The data that we will serialize and deserialize.
 
-use rustc::dep_graph::DepNode;
+use rustc::dep_graph::{DepNode, WorkProduct, WorkProductId};
 use rustc::hir::def_id::DefIndex;
+use std::sync::Arc;
 
 use super::directory::DefPathIndex;
 
@@ -55,6 +56,15 @@
     pub hash: u64,
 }
 
+#[derive(Debug, RustcEncodable, RustcDecodable)]
+pub struct SerializedWorkProduct {
+    /// node that produced the work-product
+    pub id: Arc<WorkProductId>,
+
+    /// work-product data itself
+    pub work_product: WorkProduct,
+}
+
 /// Data for use when downstream crates get recompiled.
 #[derive(Debug, RustcEncodable, RustcDecodable)]
 pub struct SerializedMetadataHashes {
diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs
index 0ac1018..36b6c79 100644
--- a/src/librustc_incremental/persist/load.rs
+++ b/src/librustc_incremental/persist/load.rs
@@ -14,12 +14,13 @@
 use rbml::opaque::Decoder;
 use rustc::dep_graph::DepNode;
 use rustc::hir::def_id::DefId;
+use rustc::session::Session;
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fnv::FnvHashSet;
 use rustc_serialize::Decodable as RustcDecodable;
 use std::io::Read;
-use std::fs::File;
-use std::path::Path;
+use std::fs::{self, File};
+use std::path::{Path};
 
 use super::data::*;
 use super::directory::*;
@@ -38,18 +39,43 @@
 /// actually it doesn't matter all that much.) See `README.md` for
 /// more general overview.
 pub fn load_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
-    let _ignore = tcx.dep_graph.in_ignore();
+    if tcx.sess.opts.incremental.is_none() {
+        return;
+    }
 
-    if let Some(dep_graph) = dep_graph_path(tcx) {
-        // FIXME(#32754) lock file?
-        load_dep_graph_if_exists(tcx, &dep_graph);
-        dirty_clean::check_dirty_clean_annotations(tcx);
+    let _ignore = tcx.dep_graph.in_ignore();
+    load_dep_graph_if_exists(tcx);
+    dirty_clean::check_dirty_clean_annotations(tcx);
+}
+
+fn load_dep_graph_if_exists<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
+    let dep_graph_path = dep_graph_path(tcx).unwrap();
+    let dep_graph_data = match load_data(tcx.sess, &dep_graph_path) {
+        Some(p) => p,
+        None => return // no file
+    };
+
+    let work_products_path = tcx_work_products_path(tcx).unwrap();
+    let work_products_data = match load_data(tcx.sess, &work_products_path) {
+        Some(p) => p,
+        None => return // no file
+    };
+
+    match decode_dep_graph(tcx, &dep_graph_data, &work_products_data) {
+        Ok(()) => return,
+        Err(err) => {
+            tcx.sess.warn(
+                &format!("decoding error in dep-graph from `{}` and `{}`: {}",
+                         dep_graph_path.display(),
+                         work_products_path.display(),
+                         err));
+        }
     }
 }
 
-pub fn load_dep_graph_if_exists<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, path: &Path) {
+fn load_data(sess: &Session, path: &Path) -> Option<Vec<u8>> {
     if !path.exists() {
-        return;
+        return None;
     }
 
     let mut data = vec![];
@@ -57,31 +83,30 @@
         File::open(path)
         .and_then(|mut file| file.read_to_end(&mut data))
     {
-        Ok(_) => { }
+        Ok(_) => {
+            Some(data)
+        }
         Err(err) => {
-            tcx.sess.err(
+            sess.err(
                 &format!("could not load dep-graph from `{}`: {}",
                          path.display(), err));
-            return;
+            None
         }
     }
 
-    match decode_dep_graph(tcx, &data) {
-        Ok(dirty) => dirty,
-        Err(err) => {
-            bug!("decoding error in dep-graph from `{}`: {}", path.display(), err);
-        }
-    }
 }
 
+/// Decode the dep graph and load the edges/nodes that are still clean
+/// into `tcx.dep_graph`.
 pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                  data: &[u8])
+                                  dep_graph_data: &[u8],
+                                  work_products_data: &[u8])
                                   -> Result<(), Error>
 {
     // Deserialize the directory and dep-graph.
-    let mut decoder = Decoder::new(data, 0);
-    let directory = try!(DefIdDirectory::decode(&mut decoder));
-    let serialized_dep_graph = try!(SerializedDepGraph::decode(&mut decoder));
+    let mut dep_graph_decoder = Decoder::new(dep_graph_data, 0);
+    let directory = try!(DefIdDirectory::decode(&mut dep_graph_decoder));
+    let serialized_dep_graph = try!(SerializedDepGraph::decode(&mut dep_graph_decoder));
 
     debug!("decode_dep_graph: directory = {:#?}", directory);
     debug!("decode_dep_graph: serialized_dep_graph = {:#?}", serialized_dep_graph);
@@ -121,12 +146,18 @@
     // Add nodes and edges that are not dirty into our main graph.
     let dep_graph = tcx.dep_graph.clone();
     for (source, target) in clean_edges.into_iter().chain(clean_nodes) {
-        let _task = dep_graph.in_task(target.clone());
-        dep_graph.read(source.clone());
-
         debug!("decode_dep_graph: clean edge: {:?} -> {:?}", source, target);
+
+        let _task = dep_graph.in_task(target);
+        dep_graph.read(source);
     }
 
+    // Add in work-products that are still clean, and delete those that are
+    // dirty.
+    let mut work_product_decoder = Decoder::new(work_products_data, 0);
+    let work_products = try!(<Vec<SerializedWorkProduct>>::decode(&mut work_product_decoder));
+    reconcile_work_products(tcx, work_products, &dirty_nodes);
+
     Ok(())
 }
 
@@ -141,9 +172,9 @@
         match hash.node.map_def(|&i| retraced.def_id(i)) {
             Some(dep_node) => {
                 let current_hash = hcx.hash(&dep_node).unwrap();
-                debug!("initial_dirty_nodes: hash of {:?} is {:?}, was {:?}",
-                       dep_node, current_hash, hash.hash);
                 if current_hash != hash.hash {
+                    debug!("initial_dirty_nodes: {:?} is dirty as hash is {:?}, was {:?}",
+                           dep_node, current_hash, hash.hash);
                     dirty_nodes.insert(dep_node);
                 }
             }
@@ -177,6 +208,8 @@
                 clean_edges.push((source, target))
             } else {
                 // source removed, target must be dirty
+                debug!("compute_clean_edges: {:?} dirty because {:?} no longer exists",
+                       target, serialized_source);
                 dirty_nodes.insert(target);
             }
         } else {
@@ -213,3 +246,51 @@
 
     clean_edges
 }
+
+/// Go through the list of work-products produced in the previous run.
+/// Delete any whose nodes have been found to be dirty or which are
+/// otherwise no longer applicable.
+fn reconcile_work_products<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                     work_products: Vec<SerializedWorkProduct>,
+                                     dirty_nodes: &DirtyNodes) {
+    debug!("reconcile_work_products({:?})", work_products);
+    for swp in work_products {
+        let dep_node = DepNode::WorkProduct(swp.id.clone());
+        if dirty_nodes.contains(&dep_node) {
+            debug!("reconcile_work_products: dep-node for {:?} is dirty", swp);
+            delete_dirty_work_product(tcx, swp);
+        } else {
+            let all_files_exist =
+                swp.work_product
+                   .saved_files
+                   .iter()
+                   .all(|&(_, ref file_name)| {
+                       let path = in_incr_comp_dir(tcx.sess, &file_name).unwrap();
+                       path.exists()
+                   });
+            if all_files_exist {
+                debug!("reconcile_work_products: all files for {:?} exist", swp);
+                tcx.dep_graph.insert_previous_work_product(&swp.id, swp.work_product);
+            } else {
+                debug!("reconcile_work_products: some file for {:?} does not exist", swp);
+                delete_dirty_work_product(tcx, swp);
+            }
+        }
+    }
+}
+
+fn delete_dirty_work_product(tcx: TyCtxt,
+                             swp: SerializedWorkProduct) {
+    debug!("delete_dirty_work_product({:?})", swp);
+    for &(_, ref file_name) in &swp.work_product.saved_files {
+        let path = in_incr_comp_dir(tcx.sess, file_name).unwrap();
+        match fs::remove_file(&path) {
+            Ok(()) => { }
+            Err(err) => {
+                tcx.sess.warn(
+                    &format!("file-system error deleting outdated file `{}`: {}",
+                             path.display(), err));
+            }
+        }
+    }
+}
diff --git a/src/librustc_incremental/persist/mod.rs b/src/librustc_incremental/persist/mod.rs
index 72ccc29..1157f49 100644
--- a/src/librustc_incremental/persist/mod.rs
+++ b/src/librustc_incremental/persist/mod.rs
@@ -19,6 +19,10 @@
 mod load;
 mod save;
 mod util;
+mod work_product;
 
 pub use self::load::load_dep_graph;
 pub use self::save::save_dep_graph;
+pub use self::save::save_work_products;
+pub use self::work_product::save_trans_partition;
+pub use self::util::in_incr_comp_dir;
diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs
index 99f4d4f..305250d 100644
--- a/src/librustc_incremental/persist/save.rs
+++ b/src/librustc_incremental/persist/save.rs
@@ -11,6 +11,7 @@
 use rbml::opaque::Encoder;
 use rustc::dep_graph::DepNode;
 use rustc::middle::cstore::LOCAL_CRATE;
+use rustc::session::Session;
 use rustc::ty::TyCtxt;
 use rustc_serialize::{Encodable as RustcEncodable};
 use std::hash::{Hasher, SipHasher};
@@ -24,19 +25,26 @@
 use super::util::*;
 
 pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
+    debug!("save_dep_graph()");
     let _ignore = tcx.dep_graph.in_ignore();
+    let sess = tcx.sess;
     let mut hcx = HashContext::new(tcx);
-    save_in(&mut hcx, dep_graph_path(tcx), encode_dep_graph);
-    save_in(&mut hcx, metadata_hash_path(tcx, LOCAL_CRATE), encode_metadata_hashes);
+    save_in(sess, dep_graph_path(tcx), |e| encode_dep_graph(&mut hcx, e));
+    save_in(sess, metadata_hash_path(tcx, LOCAL_CRATE), |e| encode_metadata_hashes(&mut hcx, e));
 }
 
-fn save_in<'a, 'tcx, F>(hcx: &mut HashContext<'a, 'tcx>,
-                        opt_path_buf: Option<PathBuf>,
-                        encode: F)
-    where F: FnOnce(&mut HashContext<'a, 'tcx>, &mut Encoder) -> io::Result<()>
-{
-    let tcx = hcx.tcx;
+pub fn save_work_products(sess: &Session, local_crate_name: &str) {
+    debug!("save_work_products()");
+    let _ignore = sess.dep_graph.in_ignore();
+    let path = sess_work_products_path(sess, local_crate_name);
+    save_in(sess, path, |e| encode_work_products(sess, e));
+}
 
+fn save_in<F>(sess: &Session,
+              opt_path_buf: Option<PathBuf>,
+              encode: F)
+    where F: FnOnce(&mut Encoder) -> io::Result<()>
+{
     let path_buf = match opt_path_buf {
         Some(p) => p,
         None => return
@@ -49,7 +57,7 @@
         match fs::remove_file(&path_buf) {
             Ok(()) => { }
             Err(err) => {
-                tcx.sess.err(
+                sess.err(
                     &format!("unable to delete old dep-graph at `{}`: {}",
                              path_buf.display(), err));
                 return;
@@ -59,10 +67,10 @@
 
     // generate the data in a memory buffer
     let mut wr = Cursor::new(Vec::new());
-    match encode(hcx, &mut Encoder::new(&mut wr)) {
+    match encode(&mut Encoder::new(&mut wr)) {
         Ok(()) => { }
         Err(err) => {
-            tcx.sess.err(
+            sess.err(
                 &format!("could not encode dep-graph to `{}`: {}",
                          path_buf.display(), err));
             return;
@@ -77,7 +85,7 @@
     {
         Ok(_) => { }
         Err(err) => {
-            tcx.sess.err(
+            sess.err(
                 &format!("failed to write dep-graph to `{}`: {}",
                          path_buf.display(), err));
             return;
@@ -192,3 +200,22 @@
 
     Ok(())
 }
+
+pub fn encode_work_products(sess: &Session,
+                            encoder: &mut Encoder)
+                            -> io::Result<()>
+{
+    let work_products: Vec<_> =
+        sess.dep_graph.work_products()
+                     .iter()
+                     .map(|(id, work_product)| {
+                         SerializedWorkProduct {
+                             id: id.clone(),
+                             work_product: work_product.clone(),
+                         }
+                     })
+                     .collect();
+
+    work_products.encode(encoder)
+}
+
diff --git a/src/librustc_incremental/persist/util.rs b/src/librustc_incremental/persist/util.rs
index a77a960..f1e81fd 100644
--- a/src/librustc_incremental/persist/util.rs
+++ b/src/librustc_incremental/persist/util.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use rustc::middle::cstore::LOCAL_CRATE;
+use rustc::session::Session;
 use rustc::ty::TyCtxt;
 
 use std::fs;
@@ -17,33 +18,56 @@
 use syntax::ast;
 
 pub fn dep_graph_path(tcx: TyCtxt) -> Option<PathBuf> {
-    path(tcx, LOCAL_CRATE, "local")
+    tcx_path(tcx, LOCAL_CRATE, "local")
 }
 
 pub fn metadata_hash_path(tcx: TyCtxt, cnum: ast::CrateNum) -> Option<PathBuf> {
-    path(tcx, cnum, "metadata")
+    tcx_path(tcx, cnum, "metadata")
 }
 
-fn path(tcx: TyCtxt, cnum: ast::CrateNum, suffix: &str) -> Option<PathBuf> {
+pub fn tcx_work_products_path(tcx: TyCtxt) -> Option<PathBuf> {
+    let crate_name = tcx.crate_name(LOCAL_CRATE);
+    sess_work_products_path(tcx.sess, &crate_name)
+}
+
+pub fn sess_work_products_path(sess: &Session,
+                               local_crate_name: &str)
+                               -> Option<PathBuf> {
+    let crate_disambiguator = sess.local_crate_disambiguator();
+    path(sess, local_crate_name, &crate_disambiguator, "work-products")
+}
+
+pub fn in_incr_comp_dir(sess: &Session, file_name: &str) -> Option<PathBuf> {
+    sess.opts.incremental.as_ref().map(|incr_dir| incr_dir.join(file_name))
+}
+
+fn tcx_path(tcx: TyCtxt,
+            cnum: ast::CrateNum,
+            middle: &str)
+            -> Option<PathBuf> {
+    path(tcx.sess, &tcx.crate_name(cnum), &tcx.crate_disambiguator(cnum), middle)
+}
+
+fn path(sess: &Session,
+        crate_name: &str,
+        crate_disambiguator: &str,
+        middle: &str)
+        -> Option<PathBuf> {
     // For now, just save/load dep-graph from
     // directory/dep_graph.rbml
-    tcx.sess.opts.incremental.as_ref().and_then(|incr_dir| {
+    sess.opts.incremental.as_ref().and_then(|incr_dir| {
         match create_dir_racy(&incr_dir) {
             Ok(()) => {}
             Err(err) => {
-                tcx.sess.err(
+                sess.err(
                     &format!("could not create the directory `{}`: {}",
                              incr_dir.display(), err));
                 return None;
             }
         }
 
-        let crate_name = tcx.crate_name(cnum);
-        let crate_disambiguator = tcx.crate_disambiguator(cnum);
-        let file_name = format!("{}-{}.{}.bin",
-                                crate_name,
-                                crate_disambiguator,
-                                suffix);
+        let file_name = format!("{}-{}.{}.bin", crate_name, crate_disambiguator, middle);
+
         Some(incr_dir.join(file_name))
     })
 }
diff --git a/src/librustc_incremental/persist/work_product.rs b/src/librustc_incremental/persist/work_product.rs
new file mode 100644
index 0000000..c106ea8
--- /dev/null
+++ b/src/librustc_incremental/persist/work_product.rs
@@ -0,0 +1,63 @@
+// Copyright 2012-2015 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.
+
+//! This module contains files for saving intermediate work-products.
+
+use persist::util::*;
+use rustc::dep_graph::{WorkProduct, WorkProductId};
+use rustc::session::Session;
+use rustc::session::config::OutputType;
+use rustc::util::fs::link_or_copy;
+use std::path::PathBuf;
+use std::sync::Arc;
+
+pub fn save_trans_partition(sess: &Session,
+                            cgu_name: &str,
+                            partition_hash: u64,
+                            files: &[(OutputType, PathBuf)]) {
+    debug!("save_trans_partition({:?},{},{:?})",
+           cgu_name,
+           partition_hash,
+           files);
+    if sess.opts.incremental.is_none() {
+        return;
+    }
+    let work_product_id = Arc::new(WorkProductId(cgu_name.to_string()));
+
+    let saved_files: Option<Vec<_>> =
+        files.iter()
+             .map(|&(kind, ref path)| {
+                 let file_name = format!("cgu-{}.{}", cgu_name, kind.extension());
+                 let path_in_incr_dir = in_incr_comp_dir(sess, &file_name).unwrap();
+                 match link_or_copy(path, &path_in_incr_dir) {
+                     Ok(_) => Some((kind, file_name)),
+                     Err(err) => {
+                         sess.warn(&format!("error copying object file `{}` \
+                                             to incremental directory as `{}`: {}",
+                                            path.display(),
+                                            path_in_incr_dir.display(),
+                                            err));
+                         None
+                     }
+                 }
+             })
+             .collect();
+    let saved_files = match saved_files {
+        Some(v) => v,
+        None => return,
+    };
+
+    let work_product = WorkProduct {
+        input_hash: partition_hash,
+        saved_files: saved_files,
+    };
+
+    sess.dep_graph.insert_work_product(&work_product_id, work_product);
+}
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 18f9733..7547e28 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -44,7 +44,7 @@
 use std::collections::HashSet;
 
 use syntax::{ast};
-use syntax::attr::{self, AttrMetaMethods};
+use syntax::attr::{self, AttrMetaMethods, AttributeMethods};
 use syntax_pos::{self, Span};
 
 use rustc::hir::{self, PatKind};
@@ -298,12 +298,7 @@
             }
         }
 
-        let has_doc = attrs.iter().any(|a| {
-            match a.node.value.node {
-                ast::MetaItemKind::NameValue(ref name, _) if *name == "doc" => true,
-                _ => false
-            }
-        });
+        let has_doc = attrs.iter().any(|a| a.is_value_str() && a.name() == "doc");
         if !has_doc {
             cx.span_lint(MISSING_DOCS, sp,
                          &format!("missing documentation for {}", desc));
@@ -1094,10 +1089,10 @@
 
 impl LateLintPass for UnstableFeatures {
     fn check_attribute(&mut self, ctx: &LateContext, attr: &ast::Attribute) {
-        if attr::contains_name(&[attr.node.value.clone()], "feature") {
-            if let Some(items) = attr.node.value.meta_item_list() {
+        if attr::contains_name(&[attr.meta().clone()], "feature") {
+            if let Some(items) = attr.meta().meta_item_list() {
                 for item in items {
-                    ctx.span_lint(UNSTABLE_FEATURES, item.span, "unstable feature");
+                    ctx.span_lint(UNSTABLE_FEATURES, item.span(), "unstable feature");
                 }
             }
         }
diff --git a/src/librustc_llvm/Cargo.toml b/src/librustc_llvm/Cargo.toml
index 05d2091..f97daa2 100644
--- a/src/librustc_llvm/Cargo.toml
+++ b/src/librustc_llvm/Cargo.toml
@@ -17,4 +17,4 @@
 
 [build-dependencies]
 build_helper = { path = "../build_helper" }
-gcc = "0.3"
+gcc = "0.3.27"
diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs
index a2c808c..b8548aa 100644
--- a/src/librustc_llvm/build.rs
+++ b/src/librustc_llvm/build.rs
@@ -13,7 +13,7 @@
 
 use std::process::Command;
 use std::env;
-use std::path::PathBuf;
+use std::path::{PathBuf, Path};
 
 use build_helper::output;
 
@@ -112,8 +112,7 @@
         cfg.flag(&flag);
     }
 
-    cfg.file("../rustllvm/ExecutionEngineWrapper.cpp")
-       .file("../rustllvm/PassWrapper.cpp")
+    cfg.file("../rustllvm/PassWrapper.cpp")
        .file("../rustllvm/RustWrapper.cpp")
        .file("../rustllvm/ArchiveWrapper.cpp")
        .cpp(true)
@@ -135,8 +134,17 @@
             &lib[2..]
         } else if lib.starts_with("-") {
             &lib[1..]
+        } else if Path::new(lib).exists() {
+            // On MSVC llvm-config will print the full name to libraries, but
+            // we're only interested in the name part
+            let name = Path::new(lib).file_name().unwrap().to_str().unwrap();
+            name.trim_right_matches(".lib")
+        } else if lib.ends_with(".lib") {
+            // Some MSVC libraries just come up with `.lib` tacked on, so chop
+            // that off
+            lib.trim_right_matches(".lib")
         } else {
-            continue;
+            continue
         };
 
         // Don't need or want this library, but LLVM's CMake build system
@@ -145,7 +153,7 @@
         // library and it otherwise may just pull in extra dependencies on
         // libedit which we don't want
         if name == "LLVMLineEditor" {
-            continue;
+            continue
         }
 
         let kind = if name.starts_with("LLVM") {
@@ -165,7 +173,9 @@
     let mut cmd = Command::new(&llvm_config);
     cmd.arg("--ldflags");
     for lib in output(&mut cmd).split_whitespace() {
-        if is_crossed {
+        if lib.starts_with("-LIBPATH:") {
+                println!("cargo:rustc-link-search=native={}", &lib[9..]);
+        } else if is_crossed {
             if lib.starts_with("-L") {
                 println!("cargo:rustc-link-search=native={}",
                          lib[2..].replace(&host, &target));
diff --git a/src/librustc_llvm/diagnostic.rs b/src/librustc_llvm/diagnostic.rs
index 44e0156..8520ae1 100644
--- a/src/librustc_llvm/diagnostic.rs
+++ b/src/librustc_llvm/diagnostic.rs
@@ -16,22 +16,29 @@
 use libc::{c_char, c_uint};
 use std::ptr;
 
-use {DebugLocRef, DiagnosticInfoRef, TwineRef, ValueRef};
+use {DiagnosticInfoRef, TwineRef, ValueRef};
+use ffi::DebugLocRef;
 
 #[derive(Copy, Clone)]
 pub enum OptimizationDiagnosticKind {
     OptimizationRemark,
     OptimizationMissed,
     OptimizationAnalysis,
+    OptimizationAnalysisFPCommute,
+    OptimizationAnalysisAliasing,
     OptimizationFailure,
+    OptimizationRemarkOther,
 }
 
 impl OptimizationDiagnosticKind {
     pub fn describe(self) -> &'static str {
         match self {
-            OptimizationRemark => "remark",
+            OptimizationRemark |
+            OptimizationRemarkOther => "remark",
             OptimizationMissed => "missed",
             OptimizationAnalysis => "analysis",
+            OptimizationAnalysisFPCommute => "floating-point",
+            OptimizationAnalysisAliasing => "aliasing",
             OptimizationFailure => "failure",
         }
     }
@@ -58,11 +65,11 @@
             message: ptr::null_mut(),
         };
 
-        super::LLVMUnpackOptimizationDiagnostic(di,
-                                                &mut opt.pass_name,
-                                                &mut opt.function,
-                                                &mut opt.debug_loc,
-                                                &mut opt.message);
+        super::LLVMRustUnpackOptimizationDiagnostic(di,
+                                                    &mut opt.pass_name,
+                                                    &mut opt.function,
+                                                    &mut opt.debug_loc,
+                                                    &mut opt.message);
 
         opt
     }
@@ -84,10 +91,10 @@
             instruction: ptr::null_mut(),
         };
 
-        super::LLVMUnpackInlineAsmDiagnostic(di,
-                                             &mut opt.cookie,
-                                             &mut opt.message,
-                                             &mut opt.instruction);
+        super::LLVMRustUnpackInlineAsmDiagnostic(di,
+                                                 &mut opt.cookie,
+                                                 &mut opt.message,
+                                                 &mut opt.instruction);
 
         opt
     }
@@ -103,24 +110,39 @@
 
 impl Diagnostic {
     pub unsafe fn unpack(di: DiagnosticInfoRef) -> Diagnostic {
-        let kind = super::LLVMGetDiagInfoKind(di);
+        use super::DiagnosticKind as Dk;
+        let kind = super::LLVMRustGetDiagInfoKind(di);
 
         match kind {
-            super::DK_InlineAsm => InlineAsm(InlineAsmDiagnostic::unpack(di)),
+            Dk::InlineAsm => InlineAsm(InlineAsmDiagnostic::unpack(di)),
 
-            super::DK_OptimizationRemark => {
+            Dk::OptimizationRemark => {
                 Optimization(OptimizationDiagnostic::unpack(OptimizationRemark, di))
             }
-
-            super::DK_OptimizationRemarkMissed => {
+            Dk::OptimizationRemarkOther => {
+                Optimization(OptimizationDiagnostic::unpack(OptimizationRemarkOther, di))
+            }
+            Dk::OptimizationRemarkMissed => {
                 Optimization(OptimizationDiagnostic::unpack(OptimizationMissed, di))
             }
 
-            super::DK_OptimizationRemarkAnalysis => {
+            Dk::OptimizationRemarkAnalysis => {
                 Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysis, di))
             }
 
-            super::DK_OptimizationFailure => {
+
+            Dk::OptimizationRemarkAnalysisFPCommute => {
+                Optimization(OptimizationDiagnostic::unpack(
+                    OptimizationAnalysisFPCommute, di))
+            }
+
+            Dk::OptimizationRemarkAnalysisAliasing => {
+                Optimization(OptimizationDiagnostic::unpack(
+                    OptimizationAnalysisAliasing, di))
+            }
+
+
+            Dk::OptimizationFailure => {
                 Optimization(OptimizationDiagnostic::unpack(OptimizationFailure, di))
             }
 
diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs
new file mode 100644
index 0000000..6301c57
--- /dev/null
+++ b/src/librustc_llvm/ffi.rs
@@ -0,0 +1,2068 @@
+// Copyright 2012-2015 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.
+
+use debuginfo::{DIBuilderRef, DIDescriptor,
+                DIFile, DILexicalBlock, DISubprogram, DIType,
+                DIBasicType, DIDerivedType, DICompositeType, DIScope,
+                DIVariable, DIGlobalVariable, DIArray, DISubrange,
+                DITemplateTypeParameter, DIEnumerator, DINameSpace};
+
+use libc::{c_uint, c_int, size_t, c_char};
+use libc::{c_longlong, c_ulonglong, c_void};
+
+use RustStringRef;
+
+pub type Opcode = u32;
+pub type Bool = c_uint;
+
+pub const True: Bool = 1 as Bool;
+pub const False: Bool = 0 as Bool;
+
+#[derive(Copy, Clone, PartialEq)]
+#[repr(C)]
+pub enum LLVMRustResult {
+    Success,
+    Failure,
+}
+// Consts for the LLVM CallConv type, pre-cast to usize.
+
+/// LLVM CallingConv::ID. Should we wrap this?
+#[derive(Copy, Clone, PartialEq)]
+#[repr(C)]
+pub enum CallConv {
+    CCallConv = 0,
+    FastCallConv = 8,
+    ColdCallConv = 9,
+    X86StdcallCallConv = 64,
+    X86FastcallCallConv = 65,
+    X86_64_Win64 = 79,
+    X86_VectorCall = 80
+}
+
+/// LLVMLinkage
+///
+/// This enum omits the obsolete (and no-op) linkage types DLLImportLinkage,
+/// DLLExportLinkage, GhostLinkage and LinkOnceODRAutoHideLinkage.
+/// LinkerPrivateLinkage and LinkerPrivateWeakLinkage are not included either;
+/// they've been removed in upstream LLVM commit r203866.
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+#[repr(C)]
+pub enum Linkage {
+    ExternalLinkage = 0,
+    AvailableExternallyLinkage = 1,
+    LinkOnceAnyLinkage = 2,
+    LinkOnceODRLinkage = 3,
+    WeakAnyLinkage = 5,
+    WeakODRLinkage = 6,
+    AppendingLinkage = 7,
+    InternalLinkage = 8,
+    PrivateLinkage = 9,
+    ExternalWeakLinkage = 12,
+    CommonLinkage = 14,
+}
+
+/// LLVMDiagnosticSeverity
+#[derive(Copy, Clone, Debug)]
+#[repr(C)]
+pub enum DiagnosticSeverity {
+    Error = 0,
+    Warning = 1,
+    Remark = 2,
+    Note = 3,
+}
+
+/// LLVMDLLStorageClass
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum DLLStorageClass {
+  Default   = 0,
+  DllImport = 1, /* Function to be imported from DLL. */
+  DllExport = 2, /* Function to be accessible from DLL. */
+}
+
+bitflags! {
+    #[derive(Default, Debug)]
+    flags Attribute : u64 {
+        const ZExt            = 1 << 0,
+        const SExt            = 1 << 1,
+        const NoReturn        = 1 << 2,
+        const InReg           = 1 << 3,
+        const StructRet       = 1 << 4,
+        const NoUnwind        = 1 << 5,
+        const NoAlias         = 1 << 6,
+        const ByVal           = 1 << 7,
+        const Nest            = 1 << 8,
+        const ReadNone        = 1 << 9,
+        const ReadOnly        = 1 << 10,
+        const NoInline        = 1 << 11,
+        const AlwaysInline    = 1 << 12,
+        const OptimizeForSize = 1 << 13,
+        const StackProtect    = 1 << 14,
+        const StackProtectReq = 1 << 15,
+        const NoCapture       = 1 << 21,
+        const NoRedZone       = 1 << 22,
+        const NoImplicitFloat = 1 << 23,
+        const Naked           = 1 << 24,
+        const InlineHint      = 1 << 25,
+        const ReturnsTwice    = 1 << 29,
+        const UWTable         = 1 << 30,
+        const NonLazyBind     = 1 << 31,
+
+        // Some of these are missing from the LLVM C API, the rest are
+        // present, but commented out, and preceded by the following warning:
+        // FIXME: These attributes are currently not included in the C API as
+        // a temporary measure until the API/ABI impact to the C API is understood
+        // and the path forward agreed upon.
+        const SanitizeAddress = 1 << 32,
+        const MinSize         = 1 << 33,
+        const NoDuplicate     = 1 << 34,
+        const StackProtectStrong = 1 << 35,
+        const SanitizeThread  = 1 << 36,
+        const SanitizeMemory  = 1 << 37,
+        const NoBuiltin       = 1 << 38,
+        const Returned        = 1 << 39,
+        const Cold            = 1 << 40,
+        const Builtin         = 1 << 41,
+        const OptimizeNone    = 1 << 42,
+        const InAlloca        = 1 << 43,
+        const NonNull         = 1 << 44,
+        const JumpTable       = 1 << 45,
+        const Convergent      = 1 << 46,
+        const SafeStack       = 1 << 47,
+        const NoRecurse       = 1 << 48,
+        const InaccessibleMemOnly         = 1 << 49,
+        const InaccessibleMemOrArgMemOnly = 1 << 50,
+    }
+}
+
+/// LLVMIntPredicate
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum IntPredicate {
+    IntEQ = 32,
+    IntNE = 33,
+    IntUGT = 34,
+    IntUGE = 35,
+    IntULT = 36,
+    IntULE = 37,
+    IntSGT = 38,
+    IntSGE = 39,
+    IntSLT = 40,
+    IntSLE = 41,
+}
+
+/// LLVMRealPredicate
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum RealPredicate {
+    RealPredicateFalse = 0,
+    RealOEQ = 1,
+    RealOGT = 2,
+    RealOGE = 3,
+    RealOLT = 4,
+    RealOLE = 5,
+    RealONE = 6,
+    RealORD = 7,
+    RealUNO = 8,
+    RealUEQ = 9,
+    RealUGT = 10,
+    RealUGE = 11,
+    RealULT = 12,
+    RealULE = 13,
+    RealUNE = 14,
+    RealPredicateTrue = 15,
+}
+
+/// LLVMTypeKind
+#[derive(Copy, Clone, PartialEq, Debug)]
+#[repr(C)]
+pub enum TypeKind {
+    Void      = 0,
+    Half      = 1,
+    Float     = 2,
+    Double    = 3,
+    X86_FP80  = 4,
+    FP128     = 5,
+    PPC_FP128 = 6,
+    Label     = 7,
+    Integer   = 8,
+    Function  = 9,
+    Struct    = 10,
+    Array     = 11,
+    Pointer   = 12,
+    Vector    = 13,
+    Metadata  = 14,
+    X86_MMX   = 15,
+    Token     = 16,
+}
+
+/// LLVMAtomicRmwBinOp
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum AtomicRmwBinOp {
+    AtomicXchg = 0,
+    AtomicAdd  = 1,
+    AtomicSub  = 2,
+    AtomicAnd  = 3,
+    AtomicNand = 4,
+    AtomicOr   = 5,
+    AtomicXor  = 6,
+    AtomicMax  = 7,
+    AtomicMin  = 8,
+    AtomicUMax = 9,
+    AtomicUMin = 10,
+}
+
+/// LLVMAtomicOrdering
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum AtomicOrdering {
+    NotAtomic = 0,
+    Unordered = 1,
+    Monotonic = 2,
+    // Consume = 3,  // Not specified yet.
+    Acquire = 4,
+    Release = 5,
+    AcquireRelease = 6,
+    SequentiallyConsistent = 7
+}
+
+/// LLVMRustSynchronizationScope
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum SynchronizationScope {
+    Other,
+    SingleThread,
+    CrossThread,
+}
+
+/// LLVMRustFileType
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum FileType {
+    Other,
+    AssemblyFile,
+    ObjectFile,
+}
+
+/// Enum pinned in LLVMContext, used in
+/// LLVMSetMetadata so ABI-stable.
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum MetadataType {
+    MD_dbg = 0,
+    MD_tbaa = 1,
+    MD_prof = 2,
+    MD_fpmath = 3,
+    MD_range = 4,
+    MD_tbaa_struct = 5,
+    MD_invariant_load = 6,
+    MD_alias_scope = 7,
+    MD_noalias = 8,
+    MD_nontemporal = 9,
+    MD_mem_parallel_loop_access = 10,
+    MD_nonnull = 11,
+}
+
+/// LLVMRustAsmDialect
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum AsmDialect {
+    Other,
+    Att,
+    Intel,
+}
+
+/// LLVMRustCodeGenOptLevel
+#[derive(Copy, Clone, PartialEq)]
+#[repr(C)]
+pub enum CodeGenOptLevel {
+    Other,
+    None,
+    Less,
+    Default,
+    Aggressive,
+}
+
+/// LLVMRelocMode
+#[derive(Copy, Clone, PartialEq)]
+#[repr(C)]
+pub enum RelocMode {
+    Default = 0,
+    Static = 1,
+    PIC = 2,
+    DynamicNoPic = 3,
+}
+
+/// LLVMRustCodeModel
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum CodeModel {
+    Other,
+    Default,
+    JITDefault,
+    Small,
+    Kernel,
+    Medium,
+    Large,
+}
+
+/// LLVMRustDiagnosticKind
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum DiagnosticKind {
+    Other,
+    InlineAsm,
+    StackSize,
+    DebugMetadataVersion,
+    SampleProfile,
+    OptimizationRemark,
+    OptimizationRemarkMissed,
+    OptimizationRemarkAnalysis,
+    OptimizationRemarkAnalysisFPCommute,
+    OptimizationRemarkAnalysisAliasing,
+    OptimizationRemarkOther,
+    OptimizationFailure,
+}
+
+/// LLVMRustArchiveKind
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum ArchiveKind {
+    Other,
+    K_GNU,
+    K_MIPS64,
+    K_BSD,
+    K_COFF,
+}
+
+/// LLVMRustPassKind
+#[derive(Copy, Clone, PartialEq, Debug)]
+#[repr(C)]
+pub enum PassKind {
+    Other,
+    Function,
+    Module,
+}
+
+// Opaque pointer types
+#[allow(missing_copy_implementations)]
+pub enum Module_opaque {}
+pub type ModuleRef = *mut Module_opaque;
+#[allow(missing_copy_implementations)]
+pub enum Context_opaque {}
+pub type ContextRef = *mut Context_opaque;
+#[allow(missing_copy_implementations)]
+pub enum Type_opaque {}
+pub type TypeRef = *mut Type_opaque;
+#[allow(missing_copy_implementations)]
+pub enum Value_opaque {}
+pub type ValueRef = *mut Value_opaque;
+#[allow(missing_copy_implementations)]
+pub enum Metadata_opaque {}
+pub type MetadataRef = *mut Metadata_opaque;
+#[allow(missing_copy_implementations)]
+pub enum BasicBlock_opaque {}
+pub type BasicBlockRef = *mut BasicBlock_opaque;
+#[allow(missing_copy_implementations)]
+pub enum Builder_opaque {}
+pub type BuilderRef = *mut Builder_opaque;
+#[allow(missing_copy_implementations)]
+pub enum ExecutionEngine_opaque {}
+pub type ExecutionEngineRef = *mut ExecutionEngine_opaque;
+#[allow(missing_copy_implementations)]
+pub enum MemoryBuffer_opaque {}
+pub type MemoryBufferRef = *mut MemoryBuffer_opaque;
+#[allow(missing_copy_implementations)]
+pub enum PassManager_opaque {}
+pub type PassManagerRef = *mut PassManager_opaque;
+#[allow(missing_copy_implementations)]
+pub enum PassManagerBuilder_opaque {}
+pub type PassManagerBuilderRef = *mut PassManagerBuilder_opaque;
+#[allow(missing_copy_implementations)]
+pub enum Use_opaque {}
+pub type UseRef = *mut Use_opaque;
+#[allow(missing_copy_implementations)]
+pub enum TargetData_opaque {}
+pub type TargetDataRef = *mut TargetData_opaque;
+#[allow(missing_copy_implementations)]
+pub enum ObjectFile_opaque {}
+pub type ObjectFileRef = *mut ObjectFile_opaque;
+#[allow(missing_copy_implementations)]
+pub enum SectionIterator_opaque {}
+pub type SectionIteratorRef = *mut SectionIterator_opaque;
+#[allow(missing_copy_implementations)]
+pub enum Pass_opaque {}
+pub type PassRef = *mut Pass_opaque;
+#[allow(missing_copy_implementations)]
+pub enum TargetMachine_opaque {}
+pub type TargetMachineRef = *mut TargetMachine_opaque;
+pub enum Archive_opaque {}
+pub type ArchiveRef = *mut Archive_opaque;
+pub enum ArchiveIterator_opaque {}
+pub type ArchiveIteratorRef = *mut ArchiveIterator_opaque;
+pub enum ArchiveChild_opaque {}
+pub type ArchiveChildRef = *mut ArchiveChild_opaque;
+#[allow(missing_copy_implementations)]
+pub enum Twine_opaque {}
+pub type TwineRef = *mut Twine_opaque;
+#[allow(missing_copy_implementations)]
+pub enum DiagnosticInfo_opaque {}
+pub type DiagnosticInfoRef = *mut DiagnosticInfo_opaque;
+#[allow(missing_copy_implementations)]
+pub enum DebugLoc_opaque {}
+pub type DebugLocRef = *mut DebugLoc_opaque;
+#[allow(missing_copy_implementations)]
+pub enum SMDiagnostic_opaque {}
+pub type SMDiagnosticRef = *mut SMDiagnostic_opaque;
+#[allow(missing_copy_implementations)]
+pub enum RustArchiveMember_opaque {}
+pub type RustArchiveMemberRef = *mut RustArchiveMember_opaque;
+#[allow(missing_copy_implementations)]
+pub enum OperandBundleDef_opaque {}
+pub type OperandBundleDefRef = *mut OperandBundleDef_opaque;
+
+pub type DiagnosticHandler = unsafe extern "C" fn(DiagnosticInfoRef, *mut c_void);
+pub type InlineAsmDiagHandler = unsafe extern "C" fn(SMDiagnosticRef, *const c_void, c_uint);
+
+pub mod debuginfo {
+    pub use self::DIDescriptorFlags::*;
+    use super::{MetadataRef};
+
+    #[allow(missing_copy_implementations)]
+    pub enum DIBuilder_opaque {}
+    pub type DIBuilderRef = *mut DIBuilder_opaque;
+
+    pub type DIDescriptor = MetadataRef;
+    pub type DIScope = DIDescriptor;
+    pub type DILocation = DIDescriptor;
+    pub type DIFile = DIScope;
+    pub type DILexicalBlock = DIScope;
+    pub type DISubprogram = DIScope;
+    pub type DINameSpace = DIScope;
+    pub type DIType = DIDescriptor;
+    pub type DIBasicType = DIType;
+    pub type DIDerivedType = DIType;
+    pub type DICompositeType = DIDerivedType;
+    pub type DIVariable = DIDescriptor;
+    pub type DIGlobalVariable = DIDescriptor;
+    pub type DIArray = DIDescriptor;
+    pub type DISubrange = DIDescriptor;
+    pub type DIEnumerator = DIDescriptor;
+    pub type DITemplateTypeParameter = DIDescriptor;
+
+    #[derive(Copy, Clone)]
+    pub enum DIDescriptorFlags {
+      FlagPrivate            = 1 << 0,
+      FlagProtected          = 1 << 1,
+      FlagFwdDecl            = 1 << 2,
+      FlagAppleBlock         = 1 << 3,
+      FlagBlockByrefStruct   = 1 << 4,
+      FlagVirtual            = 1 << 5,
+      FlagArtificial         = 1 << 6,
+      FlagExplicit           = 1 << 7,
+      FlagPrototyped         = 1 << 8,
+      FlagObjcClassComplete  = 1 << 9,
+      FlagObjectPointer      = 1 << 10,
+      FlagVector             = 1 << 11,
+      FlagStaticMember       = 1 << 12,
+      FlagIndirectVariable   = 1 << 13,
+      FlagLValueReference    = 1 << 14,
+      FlagRValueReference    = 1 << 15
+    }
+}
+
+
+// Link to our native llvm bindings (things that we need to use the C++ api
+// for) and because llvm is written in C++ we need to link against libstdc++
+//
+// You'll probably notice that there is an omission of all LLVM libraries
+// from this location. This is because the set of LLVM libraries that we
+// link to is mostly defined by LLVM, and the `llvm-config` tool is used to
+// figure out the exact set of libraries. To do this, the build system
+// generates an llvmdeps.rs file next to this one which will be
+// automatically updated whenever LLVM is updated to include an up-to-date
+// set of the libraries we need to link to LLVM for.
+#[link(name = "rustllvm", kind = "static")]
+#[cfg(not(cargobuild))]
+extern {}
+
+#[linked_from = "rustllvm"] // not quite true but good enough
+extern {
+    /* Create and destroy contexts. */
+    pub fn LLVMContextCreate() -> ContextRef;
+    pub fn LLVMContextDispose(C: ContextRef);
+    pub fn LLVMGetMDKindIDInContext(C: ContextRef,
+                                    Name: *const c_char,
+                                    SLen: c_uint)
+                                    -> c_uint;
+
+    /* Create and destroy modules. */
+    pub fn LLVMModuleCreateWithNameInContext(ModuleID: *const c_char,
+                                             C: ContextRef)
+                                             -> ModuleRef;
+    pub fn LLVMGetModuleContext(M: ModuleRef) -> ContextRef;
+    pub fn LLVMCloneModule(M: ModuleRef) -> ModuleRef;
+    pub fn LLVMDisposeModule(M: ModuleRef);
+
+    /// Data layout. See Module::getDataLayout.
+    pub fn LLVMGetDataLayout(M: ModuleRef) -> *const c_char;
+    pub fn LLVMSetDataLayout(M: ModuleRef, Triple: *const c_char);
+
+    /// Target triple. See Module::getTargetTriple.
+    pub fn LLVMGetTarget(M: ModuleRef) -> *const c_char;
+    pub fn LLVMSetTarget(M: ModuleRef, Triple: *const c_char);
+
+    /// See Module::dump.
+    pub fn LLVMDumpModule(M: ModuleRef);
+
+    /// See Module::setModuleInlineAsm.
+    pub fn LLVMSetModuleInlineAsm(M: ModuleRef, Asm: *const c_char);
+
+    /// See llvm::LLVMTypeKind::getTypeID.
+    pub fn LLVMRustGetTypeKind(Ty: TypeRef) -> TypeKind;
+
+    /// See llvm::LLVMType::getContext.
+    pub fn LLVMGetTypeContext(Ty: TypeRef) -> ContextRef;
+
+    /* Operations on integer types */
+    pub fn LLVMInt1TypeInContext(C: ContextRef) -> TypeRef;
+    pub fn LLVMInt8TypeInContext(C: ContextRef) -> TypeRef;
+    pub fn LLVMInt16TypeInContext(C: ContextRef) -> TypeRef;
+    pub fn LLVMInt32TypeInContext(C: ContextRef) -> TypeRef;
+    pub fn LLVMInt64TypeInContext(C: ContextRef) -> TypeRef;
+    pub fn LLVMIntTypeInContext(C: ContextRef, NumBits: c_uint)
+                                -> TypeRef;
+
+    pub fn LLVMGetIntTypeWidth(IntegerTy: TypeRef) -> c_uint;
+
+    /* Operations on real types */
+    pub fn LLVMFloatTypeInContext(C: ContextRef) -> TypeRef;
+    pub fn LLVMDoubleTypeInContext(C: ContextRef) -> TypeRef;
+    pub fn LLVMX86FP80TypeInContext(C: ContextRef) -> TypeRef;
+    pub fn LLVMFP128TypeInContext(C: ContextRef) -> TypeRef;
+    pub fn LLVMPPCFP128TypeInContext(C: ContextRef) -> TypeRef;
+
+    /* Operations on function types */
+    pub fn LLVMFunctionType(ReturnType: TypeRef,
+                            ParamTypes: *const TypeRef,
+                            ParamCount: c_uint,
+                            IsVarArg: Bool)
+                            -> TypeRef;
+    pub fn LLVMIsFunctionVarArg(FunctionTy: TypeRef) -> Bool;
+    pub fn LLVMGetReturnType(FunctionTy: TypeRef) -> TypeRef;
+    pub fn LLVMCountParamTypes(FunctionTy: TypeRef) -> c_uint;
+    pub fn LLVMGetParamTypes(FunctionTy: TypeRef, Dest: *mut TypeRef);
+
+    /* Operations on struct types */
+    pub fn LLVMStructTypeInContext(C: ContextRef,
+                                   ElementTypes: *const TypeRef,
+                                   ElementCount: c_uint,
+                                   Packed: Bool)
+                                   -> TypeRef;
+    pub fn LLVMCountStructElementTypes(StructTy: TypeRef) -> c_uint;
+    pub fn LLVMGetStructElementTypes(StructTy: TypeRef,
+                                     Dest: *mut TypeRef);
+    pub fn LLVMIsPackedStruct(StructTy: TypeRef) -> Bool;
+
+    /* Operations on array, pointer, and vector types (sequence types) */
+    pub fn LLVMRustArrayType(ElementType: TypeRef, ElementCount: u64) -> TypeRef;
+    pub fn LLVMPointerType(ElementType: TypeRef, AddressSpace: c_uint)
+                           -> TypeRef;
+    pub fn LLVMVectorType(ElementType: TypeRef, ElementCount: c_uint)
+                          -> TypeRef;
+
+    pub fn LLVMGetElementType(Ty: TypeRef) -> TypeRef;
+    pub fn LLVMGetArrayLength(ArrayTy: TypeRef) -> c_uint;
+    pub fn LLVMGetPointerAddressSpace(PointerTy: TypeRef) -> c_uint;
+    pub fn LLVMGetPointerToGlobal(EE: ExecutionEngineRef, V: ValueRef)
+                                  -> *const c_void;
+    pub fn LLVMGetVectorSize(VectorTy: TypeRef) -> c_uint;
+
+    /* Operations on other types */
+    pub fn LLVMVoidTypeInContext(C: ContextRef) -> TypeRef;
+    pub fn LLVMLabelTypeInContext(C: ContextRef) -> TypeRef;
+    pub fn LLVMRustMetadataTypeInContext(C: ContextRef) -> TypeRef;
+
+    /* Operations on all values */
+    pub fn LLVMTypeOf(Val: ValueRef) -> TypeRef;
+    pub fn LLVMGetValueName(Val: ValueRef) -> *const c_char;
+    pub fn LLVMSetValueName(Val: ValueRef, Name: *const c_char);
+    pub fn LLVMDumpValue(Val: ValueRef);
+    pub fn LLVMReplaceAllUsesWith(OldVal: ValueRef, NewVal: ValueRef);
+    pub fn LLVMSetMetadata(Val: ValueRef, KindID: c_uint, Node: ValueRef);
+
+    /* Operations on Uses */
+    pub fn LLVMGetFirstUse(Val: ValueRef) -> UseRef;
+    pub fn LLVMGetNextUse(U: UseRef) -> UseRef;
+    pub fn LLVMGetUser(U: UseRef) -> ValueRef;
+    pub fn LLVMGetUsedValue(U: UseRef) -> ValueRef;
+
+    /* Operations on Users */
+    pub fn LLVMGetNumOperands(Val: ValueRef) -> c_int;
+    pub fn LLVMGetOperand(Val: ValueRef, Index: c_uint) -> ValueRef;
+    pub fn LLVMSetOperand(Val: ValueRef, Index: c_uint, Op: ValueRef);
+
+    /* Operations on constants of any type */
+    pub fn LLVMConstNull(Ty: TypeRef) -> ValueRef;
+    /* all zeroes */
+    pub fn LLVMConstAllOnes(Ty: TypeRef) -> ValueRef;
+    pub fn LLVMConstICmp(Pred: IntPredicate, V1: ValueRef, V2: ValueRef)
+                         -> ValueRef;
+    pub fn LLVMConstFCmp(Pred: RealPredicate, V1: ValueRef, V2: ValueRef)
+                         -> ValueRef;
+    /* only for isize/vector */
+    pub fn LLVMGetUndef(Ty: TypeRef) -> ValueRef;
+    pub fn LLVMIsConstant(Val: ValueRef) -> Bool;
+    pub fn LLVMIsNull(Val: ValueRef) -> Bool;
+    pub fn LLVMIsUndef(Val: ValueRef) -> Bool;
+    pub fn LLVMConstPointerNull(Ty: TypeRef) -> ValueRef;
+
+    /* Operations on metadata */
+    pub fn LLVMMDStringInContext(C: ContextRef,
+                                 Str: *const c_char,
+                                 SLen: c_uint)
+                                 -> ValueRef;
+    pub fn LLVMMDNodeInContext(C: ContextRef,
+                               Vals: *const ValueRef,
+                               Count: c_uint)
+                               -> ValueRef;
+    pub fn LLVMAddNamedMetadataOperand(M: ModuleRef,
+                                       Str: *const c_char,
+                                       Val: ValueRef);
+
+    /* Operations on scalar constants */
+    pub fn LLVMConstInt(IntTy: TypeRef, N: c_ulonglong, SignExtend: Bool)
+                        -> ValueRef;
+    pub fn LLVMConstIntOfString(IntTy: TypeRef, Text: *const c_char, Radix: u8)
+                                -> ValueRef;
+    pub fn LLVMConstIntOfStringAndSize(IntTy: TypeRef,
+                                       Text: *const c_char,
+                                       SLen: c_uint,
+                                       Radix: u8)
+                                       -> ValueRef;
+    pub fn LLVMConstReal(RealTy: TypeRef, N: f64) -> ValueRef;
+    pub fn LLVMConstRealOfString(RealTy: TypeRef, Text: *const c_char)
+                                 -> ValueRef;
+    pub fn LLVMConstRealOfStringAndSize(RealTy: TypeRef,
+                                        Text: *const c_char,
+                                        SLen: c_uint)
+                                        -> ValueRef;
+    pub fn LLVMConstIntGetZExtValue(ConstantVal: ValueRef) -> c_ulonglong;
+    pub fn LLVMConstIntGetSExtValue(ConstantVal: ValueRef) -> c_longlong;
+
+
+    /* Operations on composite constants */
+    pub fn LLVMConstStringInContext(C: ContextRef,
+                                    Str: *const c_char,
+                                    Length: c_uint,
+                                    DontNullTerminate: Bool)
+                                    -> ValueRef;
+    pub fn LLVMConstStructInContext(C: ContextRef,
+                                    ConstantVals: *const ValueRef,
+                                    Count: c_uint,
+                                    Packed: Bool)
+                                    -> ValueRef;
+
+    pub fn LLVMConstArray(ElementTy: TypeRef,
+                          ConstantVals: *const ValueRef,
+                          Length: c_uint)
+                          -> ValueRef;
+    pub fn LLVMConstVector(ScalarConstantVals: *const ValueRef, Size: c_uint)
+                           -> ValueRef;
+
+    /* Constant expressions */
+    pub fn LLVMAlignOf(Ty: TypeRef) -> ValueRef;
+    pub fn LLVMSizeOf(Ty: TypeRef) -> ValueRef;
+    pub fn LLVMConstNeg(ConstantVal: ValueRef) -> ValueRef;
+    pub fn LLVMConstNSWNeg(ConstantVal: ValueRef) -> ValueRef;
+    pub fn LLVMConstNUWNeg(ConstantVal: ValueRef) -> ValueRef;
+    pub fn LLVMConstFNeg(ConstantVal: ValueRef) -> ValueRef;
+    pub fn LLVMConstNot(ConstantVal: ValueRef) -> ValueRef;
+    pub fn LLVMConstAdd(LHSConstant: ValueRef, RHSConstant: ValueRef)
+                        -> ValueRef;
+    pub fn LLVMConstNSWAdd(LHSConstant: ValueRef, RHSConstant: ValueRef)
+                           -> ValueRef;
+    pub fn LLVMConstNUWAdd(LHSConstant: ValueRef, RHSConstant: ValueRef)
+                           -> ValueRef;
+    pub fn LLVMConstFAdd(LHSConstant: ValueRef, RHSConstant: ValueRef)
+                         -> ValueRef;
+    pub fn LLVMConstSub(LHSConstant: ValueRef, RHSConstant: ValueRef)
+                        -> ValueRef;
+    pub fn LLVMConstNSWSub(LHSConstant: ValueRef, RHSConstant: ValueRef)
+                           -> ValueRef;
+    pub fn LLVMConstNUWSub(LHSConstant: ValueRef, RHSConstant: ValueRef)
+                           -> ValueRef;
+    pub fn LLVMConstFSub(LHSConstant: ValueRef, RHSConstant: ValueRef)
+                         -> ValueRef;
+    pub fn LLVMConstMul(LHSConstant: ValueRef, RHSConstant: ValueRef)
+                        -> ValueRef;
+    pub fn LLVMConstNSWMul(LHSConstant: ValueRef, RHSConstant: ValueRef)
+                           -> ValueRef;
+    pub fn LLVMConstNUWMul(LHSConstant: ValueRef, RHSConstant: ValueRef)
+                           -> ValueRef;
+    pub fn LLVMConstFMul(LHSConstant: ValueRef, RHSConstant: ValueRef)
+                         -> ValueRef;
+    pub fn LLVMConstUDiv(LHSConstant: ValueRef, RHSConstant: ValueRef)
+                         -> ValueRef;
+    pub fn LLVMConstSDiv(LHSConstant: ValueRef, RHSConstant: ValueRef)
+                         -> ValueRef;
+    pub fn LLVMConstExactSDiv(LHSConstant: ValueRef,
+                              RHSConstant: ValueRef)
+                              -> ValueRef;
+    pub fn LLVMConstFDiv(LHSConstant: ValueRef, RHSConstant: ValueRef)
+                         -> ValueRef;
+    pub fn LLVMConstURem(LHSConstant: ValueRef, RHSConstant: ValueRef)
+                         -> ValueRef;
+    pub fn LLVMConstSRem(LHSConstant: ValueRef, RHSConstant: ValueRef)
+                         -> ValueRef;
+    pub fn LLVMConstFRem(LHSConstant: ValueRef, RHSConstant: ValueRef)
+                         -> ValueRef;
+    pub fn LLVMConstAnd(LHSConstant: ValueRef, RHSConstant: ValueRef)
+                        -> ValueRef;
+    pub fn LLVMConstOr(LHSConstant: ValueRef, RHSConstant: ValueRef)
+                       -> ValueRef;
+    pub fn LLVMConstXor(LHSConstant: ValueRef, RHSConstant: ValueRef)
+                        -> ValueRef;
+    pub fn LLVMConstShl(LHSConstant: ValueRef, RHSConstant: ValueRef)
+                        -> ValueRef;
+    pub fn LLVMConstLShr(LHSConstant: ValueRef, RHSConstant: ValueRef)
+                         -> ValueRef;
+    pub fn LLVMConstAShr(LHSConstant: ValueRef, RHSConstant: ValueRef)
+                         -> ValueRef;
+    pub fn LLVMConstGEP(ConstantVal: ValueRef,
+                        ConstantIndices: *const ValueRef,
+                        NumIndices: c_uint)
+                        -> ValueRef;
+    pub fn LLVMConstInBoundsGEP(ConstantVal: ValueRef,
+                                ConstantIndices: *const ValueRef,
+                                NumIndices: c_uint)
+                                -> ValueRef;
+    pub fn LLVMConstTrunc(ConstantVal: ValueRef, ToType: TypeRef)
+                          -> ValueRef;
+    pub fn LLVMConstSExt(ConstantVal: ValueRef, ToType: TypeRef)
+                         -> ValueRef;
+    pub fn LLVMConstZExt(ConstantVal: ValueRef, ToType: TypeRef)
+                         -> ValueRef;
+    pub fn LLVMConstFPTrunc(ConstantVal: ValueRef, ToType: TypeRef)
+                            -> ValueRef;
+    pub fn LLVMConstFPExt(ConstantVal: ValueRef, ToType: TypeRef)
+                          -> ValueRef;
+    pub fn LLVMConstUIToFP(ConstantVal: ValueRef, ToType: TypeRef)
+                           -> ValueRef;
+    pub fn LLVMConstSIToFP(ConstantVal: ValueRef, ToType: TypeRef)
+                           -> ValueRef;
+    pub fn LLVMConstFPToUI(ConstantVal: ValueRef, ToType: TypeRef)
+                           -> ValueRef;
+    pub fn LLVMConstFPToSI(ConstantVal: ValueRef, ToType: TypeRef)
+                           -> ValueRef;
+    pub fn LLVMConstPtrToInt(ConstantVal: ValueRef, ToType: TypeRef)
+                             -> ValueRef;
+    pub fn LLVMConstIntToPtr(ConstantVal: ValueRef, ToType: TypeRef)
+                             -> ValueRef;
+    pub fn LLVMConstBitCast(ConstantVal: ValueRef, ToType: TypeRef)
+                            -> ValueRef;
+    pub fn LLVMConstZExtOrBitCast(ConstantVal: ValueRef, ToType: TypeRef)
+                                  -> ValueRef;
+    pub fn LLVMConstSExtOrBitCast(ConstantVal: ValueRef, ToType: TypeRef)
+                                  -> ValueRef;
+    pub fn LLVMConstTruncOrBitCast(ConstantVal: ValueRef, ToType: TypeRef)
+                                   -> ValueRef;
+    pub fn LLVMConstPointerCast(ConstantVal: ValueRef, ToType: TypeRef)
+                                -> ValueRef;
+    pub fn LLVMConstIntCast(ConstantVal: ValueRef,
+                            ToType: TypeRef,
+                            isSigned: Bool)
+                            -> ValueRef;
+    pub fn LLVMConstFPCast(ConstantVal: ValueRef, ToType: TypeRef)
+                           -> ValueRef;
+    pub fn LLVMConstSelect(ConstantCondition: ValueRef,
+                           ConstantIfTrue: ValueRef,
+                           ConstantIfFalse: ValueRef)
+                           -> ValueRef;
+    pub fn LLVMConstExtractElement(VectorConstant: ValueRef,
+                                   IndexConstant: ValueRef)
+                                   -> ValueRef;
+    pub fn LLVMConstInsertElement(VectorConstant: ValueRef,
+                                  ElementValueConstant: ValueRef,
+                                  IndexConstant: ValueRef)
+                                  -> ValueRef;
+    pub fn LLVMConstShuffleVector(VectorAConstant: ValueRef,
+                                  VectorBConstant: ValueRef,
+                                  MaskConstant: ValueRef)
+                                  -> ValueRef;
+    pub fn LLVMConstExtractValue(AggConstant: ValueRef,
+                                 IdxList: *const c_uint,
+                                 NumIdx: c_uint)
+                                 -> ValueRef;
+    pub fn LLVMConstInsertValue(AggConstant: ValueRef,
+                                ElementValueConstant: ValueRef,
+                                IdxList: *const c_uint,
+                                NumIdx: c_uint)
+                                -> ValueRef;
+    pub fn LLVMConstInlineAsm(Ty: TypeRef,
+                              AsmString: *const c_char,
+                              Constraints: *const c_char,
+                              HasSideEffects: Bool,
+                              IsAlignStack: Bool)
+                              -> ValueRef;
+    pub fn LLVMBlockAddress(F: ValueRef, BB: BasicBlockRef) -> ValueRef;
+
+
+
+    /* Operations on global variables, functions, and aliases (globals) */
+    pub fn LLVMGetGlobalParent(Global: ValueRef) -> ModuleRef;
+    pub fn LLVMIsDeclaration(Global: ValueRef) -> Bool;
+    pub fn LLVMGetLinkage(Global: ValueRef) -> c_uint;
+    pub fn LLVMSetLinkage(Global: ValueRef, Link: Linkage);
+    pub fn LLVMGetSection(Global: ValueRef) -> *const c_char;
+    pub fn LLVMSetSection(Global: ValueRef, Section: *const c_char);
+    pub fn LLVMGetVisibility(Global: ValueRef) -> c_uint;
+    pub fn LLVMSetVisibility(Global: ValueRef, Viz: c_uint);
+    pub fn LLVMGetAlignment(Global: ValueRef) -> c_uint;
+    pub fn LLVMSetAlignment(Global: ValueRef, Bytes: c_uint);
+    pub fn LLVMSetDLLStorageClass(V: ValueRef,
+                                  C: DLLStorageClass);
+
+
+    /* Operations on global variables */
+    pub fn LLVMIsAGlobalVariable(GlobalVar: ValueRef) -> ValueRef;
+    pub fn LLVMAddGlobal(M: ModuleRef, Ty: TypeRef, Name: *const c_char)
+                         -> ValueRef;
+    pub fn LLVMAddGlobalInAddressSpace(M: ModuleRef,
+                                       Ty: TypeRef,
+                                       Name: *const c_char,
+                                       AddressSpace: c_uint)
+                                       -> ValueRef;
+    pub fn LLVMGetNamedGlobal(M: ModuleRef,
+                              Name: *const c_char)
+                              -> ValueRef;
+    pub fn LLVMRustGetOrInsertGlobal(M: ModuleRef,
+                                     Name: *const c_char,
+                                     T: TypeRef)
+                                     -> ValueRef;
+    pub fn LLVMGetFirstGlobal(M: ModuleRef) -> ValueRef;
+    pub fn LLVMGetLastGlobal(M: ModuleRef) -> ValueRef;
+    pub fn LLVMGetNextGlobal(GlobalVar: ValueRef) -> ValueRef;
+    pub fn LLVMGetPreviousGlobal(GlobalVar: ValueRef) -> ValueRef;
+    pub fn LLVMDeleteGlobal(GlobalVar: ValueRef);
+    pub fn LLVMGetInitializer(GlobalVar: ValueRef) -> ValueRef;
+    pub fn LLVMSetInitializer(GlobalVar: ValueRef,
+                              ConstantVal: ValueRef);
+    pub fn LLVMIsThreadLocal(GlobalVar: ValueRef) -> Bool;
+    pub fn LLVMSetThreadLocal(GlobalVar: ValueRef, IsThreadLocal: Bool);
+    pub fn LLVMIsGlobalConstant(GlobalVar: ValueRef) -> Bool;
+    pub fn LLVMSetGlobalConstant(GlobalVar: ValueRef, IsConstant: Bool);
+    pub fn LLVMRustGetNamedValue(M: ModuleRef, Name: *const c_char) -> ValueRef;
+
+    /* Operations on aliases */
+    pub fn LLVMAddAlias(M: ModuleRef,
+                        Ty: TypeRef,
+                        Aliasee: ValueRef,
+                        Name: *const c_char)
+                        -> ValueRef;
+
+    /* Operations on functions */
+    pub fn LLVMAddFunction(M: ModuleRef,
+                           Name: *const c_char,
+                           FunctionTy: TypeRef)
+                           -> ValueRef;
+    pub fn LLVMGetNamedFunction(M: ModuleRef, Name: *const c_char) -> ValueRef;
+    pub fn LLVMGetFirstFunction(M: ModuleRef) -> ValueRef;
+    pub fn LLVMGetLastFunction(M: ModuleRef) -> ValueRef;
+    pub fn LLVMGetNextFunction(Fn: ValueRef) -> ValueRef;
+    pub fn LLVMGetPreviousFunction(Fn: ValueRef) -> ValueRef;
+    pub fn LLVMDeleteFunction(Fn: ValueRef);
+    pub fn LLVMRustGetOrInsertFunction(M: ModuleRef,
+                                       Name: *const c_char,
+                                       FunctionTy: TypeRef)
+                                       -> ValueRef;
+    pub fn LLVMGetIntrinsicID(Fn: ValueRef) -> c_uint;
+    pub fn LLVMGetFunctionCallConv(Fn: ValueRef) -> c_uint;
+    pub fn LLVMSetFunctionCallConv(Fn: ValueRef, CC: c_uint);
+    pub fn LLVMGetGC(Fn: ValueRef) -> *const c_char;
+    pub fn LLVMSetGC(Fn: ValueRef, Name: *const c_char);
+    pub fn LLVMRustAddDereferenceableAttr(Fn: ValueRef, index: c_uint, bytes: u64);
+    pub fn LLVMRustAddFunctionAttribute(Fn: ValueRef, index: c_uint, PA: u64);
+    pub fn LLVMRustAddFunctionAttrString(Fn: ValueRef, index: c_uint, Name: *const c_char);
+    pub fn LLVMRustAddFunctionAttrStringValue(Fn: ValueRef, index: c_uint,
+                                              Name: *const c_char,
+                                              Value: *const c_char);
+    pub fn LLVMRustRemoveFunctionAttributes(Fn: ValueRef,
+                                            index: c_uint,
+                                            attr: u64);
+    pub fn LLVMRustRemoveFunctionAttrString(Fn: ValueRef,
+                                            index: c_uint,
+                                            Name: *const c_char);
+    pub fn LLVMGetFunctionAttr(Fn: ValueRef) -> c_uint;
+    pub fn LLVMRemoveFunctionAttr(Fn: ValueRef, val: c_uint);
+
+    /* Operations on parameters */
+    pub fn LLVMCountParams(Fn: ValueRef) -> c_uint;
+    pub fn LLVMGetParams(Fn: ValueRef, Params: *const ValueRef);
+    pub fn LLVMGetParam(Fn: ValueRef, Index: c_uint) -> ValueRef;
+    pub fn LLVMGetParamParent(Inst: ValueRef) -> ValueRef;
+    pub fn LLVMGetFirstParam(Fn: ValueRef) -> ValueRef;
+    pub fn LLVMGetLastParam(Fn: ValueRef) -> ValueRef;
+    pub fn LLVMGetNextParam(Arg: ValueRef) -> ValueRef;
+    pub fn LLVMGetPreviousParam(Arg: ValueRef) -> ValueRef;
+    pub fn LLVMAddAttribute(Arg: ValueRef, PA: c_uint);
+    pub fn LLVMRemoveAttribute(Arg: ValueRef, PA: c_uint);
+    pub fn LLVMGetAttribute(Arg: ValueRef) -> c_uint;
+    pub fn LLVMSetParamAlignment(Arg: ValueRef, align: c_uint);
+
+    /* Operations on basic blocks */
+    pub fn LLVMBasicBlockAsValue(BB: BasicBlockRef) -> ValueRef;
+    pub fn LLVMValueIsBasicBlock(Val: ValueRef) -> Bool;
+    pub fn LLVMValueAsBasicBlock(Val: ValueRef) -> BasicBlockRef;
+    pub fn LLVMGetBasicBlockParent(BB: BasicBlockRef) -> ValueRef;
+    pub fn LLVMCountBasicBlocks(Fn: ValueRef) -> c_uint;
+    pub fn LLVMGetBasicBlocks(Fn: ValueRef, BasicBlocks: *const ValueRef);
+    pub fn LLVMGetFirstBasicBlock(Fn: ValueRef) -> BasicBlockRef;
+    pub fn LLVMGetLastBasicBlock(Fn: ValueRef) -> BasicBlockRef;
+    pub fn LLVMGetNextBasicBlock(BB: BasicBlockRef) -> BasicBlockRef;
+    pub fn LLVMGetPreviousBasicBlock(BB: BasicBlockRef) -> BasicBlockRef;
+    pub fn LLVMGetEntryBasicBlock(Fn: ValueRef) -> BasicBlockRef;
+
+    pub fn LLVMAppendBasicBlockInContext(C: ContextRef,
+                                         Fn: ValueRef,
+                                         Name: *const c_char)
+                                         -> BasicBlockRef;
+    pub fn LLVMInsertBasicBlockInContext(C: ContextRef,
+                                         BB: BasicBlockRef,
+                                         Name: *const c_char)
+                                         -> BasicBlockRef;
+    pub fn LLVMDeleteBasicBlock(BB: BasicBlockRef);
+
+    pub fn LLVMMoveBasicBlockAfter(BB: BasicBlockRef,
+                                   MoveAfter: BasicBlockRef);
+
+    pub fn LLVMMoveBasicBlockBefore(BB: BasicBlockRef,
+                                    MoveBefore: BasicBlockRef);
+
+    /* Operations on instructions */
+    pub fn LLVMGetInstructionParent(Inst: ValueRef) -> BasicBlockRef;
+    pub fn LLVMGetFirstInstruction(BB: BasicBlockRef) -> ValueRef;
+    pub fn LLVMGetLastInstruction(BB: BasicBlockRef) -> ValueRef;
+    pub fn LLVMGetNextInstruction(Inst: ValueRef) -> ValueRef;
+    pub fn LLVMGetPreviousInstruction(Inst: ValueRef) -> ValueRef;
+    pub fn LLVMInstructionEraseFromParent(Inst: ValueRef);
+
+    /* Operations on call sites */
+    pub fn LLVMSetInstructionCallConv(Instr: ValueRef, CC: c_uint);
+    pub fn LLVMGetInstructionCallConv(Instr: ValueRef) -> c_uint;
+    pub fn LLVMAddInstrAttribute(Instr: ValueRef,
+                                 index: c_uint,
+                                 IA: c_uint);
+    pub fn LLVMRemoveInstrAttribute(Instr: ValueRef,
+                                    index: c_uint,
+                                    IA: c_uint);
+    pub fn LLVMSetInstrParamAlignment(Instr: ValueRef,
+                                      index: c_uint,
+                                      align: c_uint);
+    pub fn LLVMRustAddCallSiteAttribute(Instr: ValueRef,
+                                    index: c_uint,
+                                    Val: u64);
+    pub fn LLVMRustAddDereferenceableCallSiteAttr(Instr: ValueRef,
+                                                  index: c_uint,
+                                                  bytes: u64);
+
+    /* Operations on call instructions (only) */
+    pub fn LLVMIsTailCall(CallInst: ValueRef) -> Bool;
+    pub fn LLVMSetTailCall(CallInst: ValueRef, IsTailCall: Bool);
+
+    /* Operations on load/store instructions (only) */
+    pub fn LLVMGetVolatile(MemoryAccessInst: ValueRef) -> Bool;
+    pub fn LLVMSetVolatile(MemoryAccessInst: ValueRef, volatile: Bool);
+
+    /* Operations on phi nodes */
+    pub fn LLVMAddIncoming(PhiNode: ValueRef,
+                           IncomingValues: *const ValueRef,
+                           IncomingBlocks: *const BasicBlockRef,
+                           Count: c_uint);
+    pub fn LLVMCountIncoming(PhiNode: ValueRef) -> c_uint;
+    pub fn LLVMGetIncomingValue(PhiNode: ValueRef, Index: c_uint)
+                                -> ValueRef;
+    pub fn LLVMGetIncomingBlock(PhiNode: ValueRef, Index: c_uint)
+                                -> BasicBlockRef;
+
+    /* Instruction builders */
+    pub fn LLVMCreateBuilderInContext(C: ContextRef) -> BuilderRef;
+    pub fn LLVMPositionBuilder(Builder: BuilderRef,
+                               Block: BasicBlockRef,
+                               Instr: ValueRef);
+    pub fn LLVMPositionBuilderBefore(Builder: BuilderRef,
+                                     Instr: ValueRef);
+    pub fn LLVMPositionBuilderAtEnd(Builder: BuilderRef,
+                                    Block: BasicBlockRef);
+    pub fn LLVMGetInsertBlock(Builder: BuilderRef) -> BasicBlockRef;
+    pub fn LLVMClearInsertionPosition(Builder: BuilderRef);
+    pub fn LLVMInsertIntoBuilder(Builder: BuilderRef, Instr: ValueRef);
+    pub fn LLVMInsertIntoBuilderWithName(Builder: BuilderRef,
+                                         Instr: ValueRef,
+                                         Name: *const c_char);
+    pub fn LLVMDisposeBuilder(Builder: BuilderRef);
+
+    /* Metadata */
+    pub fn LLVMSetCurrentDebugLocation(Builder: BuilderRef, L: ValueRef);
+    pub fn LLVMGetCurrentDebugLocation(Builder: BuilderRef) -> ValueRef;
+    pub fn LLVMSetInstDebugLocation(Builder: BuilderRef, Inst: ValueRef);
+
+    /* Terminators */
+    pub fn LLVMBuildRetVoid(B: BuilderRef) -> ValueRef;
+    pub fn LLVMBuildRet(B: BuilderRef, V: ValueRef) -> ValueRef;
+    pub fn LLVMBuildAggregateRet(B: BuilderRef,
+                                 RetVals: *const ValueRef,
+                                 N: c_uint)
+                                 -> ValueRef;
+    pub fn LLVMBuildBr(B: BuilderRef, Dest: BasicBlockRef) -> ValueRef;
+    pub fn LLVMBuildCondBr(B: BuilderRef,
+                           If: ValueRef,
+                           Then: BasicBlockRef,
+                           Else: BasicBlockRef)
+                           -> ValueRef;
+    pub fn LLVMBuildSwitch(B: BuilderRef,
+                           V: ValueRef,
+                           Else: BasicBlockRef,
+                           NumCases: c_uint)
+                           -> ValueRef;
+    pub fn LLVMBuildIndirectBr(B: BuilderRef,
+                               Addr: ValueRef,
+                               NumDests: c_uint)
+                               -> ValueRef;
+    pub fn LLVMRustBuildInvoke(B: BuilderRef,
+                               Fn: ValueRef,
+                               Args: *const ValueRef,
+                               NumArgs: c_uint,
+                               Then: BasicBlockRef,
+                               Catch: BasicBlockRef,
+                               Bundle: OperandBundleDefRef,
+                               Name: *const c_char)
+                               -> ValueRef;
+    pub fn LLVMRustBuildLandingPad(B: BuilderRef,
+                                   Ty: TypeRef,
+                                   PersFn: ValueRef,
+                                   NumClauses: c_uint,
+                                   Name: *const c_char,
+                                   F: ValueRef)
+                                   -> ValueRef;
+    pub fn LLVMBuildResume(B: BuilderRef, Exn: ValueRef) -> ValueRef;
+    pub fn LLVMBuildUnreachable(B: BuilderRef) -> ValueRef;
+
+    pub fn LLVMRustBuildCleanupPad(B: BuilderRef,
+                                   ParentPad: ValueRef,
+                                   ArgCnt: c_uint,
+                                   Args: *const ValueRef,
+                                   Name: *const c_char) -> ValueRef;
+    pub fn LLVMRustBuildCleanupRet(B: BuilderRef,
+                                   CleanupPad: ValueRef,
+                                   UnwindBB: BasicBlockRef) -> ValueRef;
+    pub fn LLVMRustBuildCatchPad(B: BuilderRef,
+                                 ParentPad: ValueRef,
+                                 ArgCnt: c_uint,
+                                 Args: *const ValueRef,
+                                 Name: *const c_char) -> ValueRef;
+    pub fn LLVMRustBuildCatchRet(B: BuilderRef,
+                                 Pad: ValueRef,
+                                 BB: BasicBlockRef) -> ValueRef;
+    pub fn LLVMRustBuildCatchSwitch(Builder: BuilderRef,
+                                    ParentPad: ValueRef,
+                                    BB: BasicBlockRef,
+                                    NumHandlers: c_uint,
+                                    Name: *const c_char) -> ValueRef;
+    pub fn LLVMRustAddHandler(CatchSwitch: ValueRef,
+                              Handler: BasicBlockRef);
+    pub fn LLVMRustSetPersonalityFn(B: BuilderRef, Pers: ValueRef);
+
+    /* Add a case to the switch instruction */
+    pub fn LLVMAddCase(Switch: ValueRef,
+                       OnVal: ValueRef,
+                       Dest: BasicBlockRef);
+
+    /* Add a destination to the indirectbr instruction */
+    pub fn LLVMAddDestination(IndirectBr: ValueRef, Dest: BasicBlockRef);
+
+    /* Add a clause to the landing pad instruction */
+    pub fn LLVMAddClause(LandingPad: ValueRef, ClauseVal: ValueRef);
+
+    /* Set the cleanup on a landing pad instruction */
+    pub fn LLVMSetCleanup(LandingPad: ValueRef, Val: Bool);
+
+    /* Arithmetic */
+    pub fn LLVMBuildAdd(B: BuilderRef,
+                        LHS: ValueRef,
+                        RHS: ValueRef,
+                        Name: *const c_char)
+                        -> ValueRef;
+    pub fn LLVMBuildNSWAdd(B: BuilderRef,
+                           LHS: ValueRef,
+                           RHS: ValueRef,
+                           Name: *const c_char)
+                           -> ValueRef;
+    pub fn LLVMBuildNUWAdd(B: BuilderRef,
+                           LHS: ValueRef,
+                           RHS: ValueRef,
+                           Name: *const c_char)
+                           -> ValueRef;
+    pub fn LLVMBuildFAdd(B: BuilderRef,
+                         LHS: ValueRef,
+                         RHS: ValueRef,
+                         Name: *const c_char)
+                         -> ValueRef;
+    pub fn LLVMBuildSub(B: BuilderRef,
+                        LHS: ValueRef,
+                        RHS: ValueRef,
+                        Name: *const c_char)
+                        -> ValueRef;
+    pub fn LLVMBuildNSWSub(B: BuilderRef,
+                           LHS: ValueRef,
+                           RHS: ValueRef,
+                           Name: *const c_char)
+                           -> ValueRef;
+    pub fn LLVMBuildNUWSub(B: BuilderRef,
+                           LHS: ValueRef,
+                           RHS: ValueRef,
+                           Name: *const c_char)
+                           -> ValueRef;
+    pub fn LLVMBuildFSub(B: BuilderRef,
+                         LHS: ValueRef,
+                         RHS: ValueRef,
+                         Name: *const c_char)
+                         -> ValueRef;
+    pub fn LLVMBuildMul(B: BuilderRef,
+                        LHS: ValueRef,
+                        RHS: ValueRef,
+                        Name: *const c_char)
+                        -> ValueRef;
+    pub fn LLVMBuildNSWMul(B: BuilderRef,
+                           LHS: ValueRef,
+                           RHS: ValueRef,
+                           Name: *const c_char)
+                           -> ValueRef;
+    pub fn LLVMBuildNUWMul(B: BuilderRef,
+                           LHS: ValueRef,
+                           RHS: ValueRef,
+                           Name: *const c_char)
+                           -> ValueRef;
+    pub fn LLVMBuildFMul(B: BuilderRef,
+                         LHS: ValueRef,
+                         RHS: ValueRef,
+                         Name: *const c_char)
+                         -> ValueRef;
+    pub fn LLVMBuildUDiv(B: BuilderRef,
+                         LHS: ValueRef,
+                         RHS: ValueRef,
+                         Name: *const c_char)
+                         -> ValueRef;
+    pub fn LLVMBuildSDiv(B: BuilderRef,
+                         LHS: ValueRef,
+                         RHS: ValueRef,
+                         Name: *const c_char)
+                         -> ValueRef;
+    pub fn LLVMBuildExactSDiv(B: BuilderRef,
+                              LHS: ValueRef,
+                              RHS: ValueRef,
+                              Name: *const c_char)
+                              -> ValueRef;
+    pub fn LLVMBuildFDiv(B: BuilderRef,
+                         LHS: ValueRef,
+                         RHS: ValueRef,
+                         Name: *const c_char)
+                         -> ValueRef;
+    pub fn LLVMBuildURem(B: BuilderRef,
+                         LHS: ValueRef,
+                         RHS: ValueRef,
+                         Name: *const c_char)
+                         -> ValueRef;
+    pub fn LLVMBuildSRem(B: BuilderRef,
+                         LHS: ValueRef,
+                         RHS: ValueRef,
+                         Name: *const c_char)
+                         -> ValueRef;
+    pub fn LLVMBuildFRem(B: BuilderRef,
+                         LHS: ValueRef,
+                         RHS: ValueRef,
+                         Name: *const c_char)
+                         -> ValueRef;
+    pub fn LLVMBuildShl(B: BuilderRef,
+                        LHS: ValueRef,
+                        RHS: ValueRef,
+                        Name: *const c_char)
+                        -> ValueRef;
+    pub fn LLVMBuildLShr(B: BuilderRef,
+                         LHS: ValueRef,
+                         RHS: ValueRef,
+                         Name: *const c_char)
+                         -> ValueRef;
+    pub fn LLVMBuildAShr(B: BuilderRef,
+                         LHS: ValueRef,
+                         RHS: ValueRef,
+                         Name: *const c_char)
+                         -> ValueRef;
+    pub fn LLVMBuildAnd(B: BuilderRef,
+                        LHS: ValueRef,
+                        RHS: ValueRef,
+                        Name: *const c_char)
+                        -> ValueRef;
+    pub fn LLVMBuildOr(B: BuilderRef,
+                       LHS: ValueRef,
+                       RHS: ValueRef,
+                       Name: *const c_char)
+                           -> ValueRef;
+    pub fn LLVMBuildXor(B: BuilderRef,
+                        LHS: ValueRef,
+                        RHS: ValueRef,
+                        Name: *const c_char)
+                        -> ValueRef;
+    pub fn LLVMBuildBinOp(B: BuilderRef,
+                          Op: Opcode,
+                          LHS: ValueRef,
+                          RHS: ValueRef,
+                          Name: *const c_char)
+                          -> ValueRef;
+    pub fn LLVMBuildNeg(B: BuilderRef, V: ValueRef, Name: *const c_char)
+                        -> ValueRef;
+    pub fn LLVMBuildNSWNeg(B: BuilderRef, V: ValueRef, Name: *const c_char)
+                           -> ValueRef;
+    pub fn LLVMBuildNUWNeg(B: BuilderRef, V: ValueRef, Name: *const c_char)
+                           -> ValueRef;
+    pub fn LLVMBuildFNeg(B: BuilderRef, V: ValueRef, Name: *const c_char)
+                         -> ValueRef;
+    pub fn LLVMBuildNot(B: BuilderRef, V: ValueRef, Name: *const c_char)
+                        -> ValueRef;
+    pub fn LLVMRustSetHasUnsafeAlgebra(Instr: ValueRef);
+
+    /* Memory */
+    pub fn LLVMBuildAlloca(B: BuilderRef, Ty: TypeRef, Name: *const c_char)
+                           -> ValueRef;
+    pub fn LLVMBuildFree(B: BuilderRef, PointerVal: ValueRef) -> ValueRef;
+    pub fn LLVMBuildLoad(B: BuilderRef,
+                         PointerVal: ValueRef,
+                         Name: *const c_char)
+                         -> ValueRef;
+
+    pub fn LLVMBuildStore(B: BuilderRef, Val: ValueRef, Ptr: ValueRef)
+                          -> ValueRef;
+
+    pub fn LLVMBuildGEP(B: BuilderRef,
+                        Pointer: ValueRef,
+                        Indices: *const ValueRef,
+                        NumIndices: c_uint,
+                        Name: *const c_char)
+                        -> ValueRef;
+    pub fn LLVMBuildInBoundsGEP(B: BuilderRef,
+                                Pointer: ValueRef,
+                                Indices: *const ValueRef,
+                                NumIndices: c_uint,
+                                Name: *const c_char)
+                                -> ValueRef;
+    pub fn LLVMBuildStructGEP(B: BuilderRef,
+                              Pointer: ValueRef,
+                              Idx: c_uint,
+                              Name: *const c_char)
+                              -> ValueRef;
+    pub fn LLVMBuildGlobalString(B: BuilderRef,
+                                 Str: *const c_char,
+                                 Name: *const c_char)
+                                 -> ValueRef;
+    pub fn LLVMBuildGlobalStringPtr(B: BuilderRef,
+                                    Str: *const c_char,
+                                    Name: *const c_char)
+                                    -> ValueRef;
+
+    /* Casts */
+    pub fn LLVMBuildTrunc(B: BuilderRef,
+                          Val: ValueRef,
+                          DestTy: TypeRef,
+                          Name: *const c_char)
+                          -> ValueRef;
+    pub fn LLVMBuildZExt(B: BuilderRef,
+                         Val: ValueRef,
+                         DestTy: TypeRef,
+                         Name: *const c_char)
+                         -> ValueRef;
+    pub fn LLVMBuildSExt(B: BuilderRef,
+                         Val: ValueRef,
+                         DestTy: TypeRef,
+                         Name: *const c_char)
+                         -> ValueRef;
+    pub fn LLVMBuildFPToUI(B: BuilderRef,
+                           Val: ValueRef,
+                           DestTy: TypeRef,
+                           Name: *const c_char)
+                           -> ValueRef;
+    pub fn LLVMBuildFPToSI(B: BuilderRef,
+                           Val: ValueRef,
+                           DestTy: TypeRef,
+                           Name: *const c_char)
+                           -> ValueRef;
+    pub fn LLVMBuildUIToFP(B: BuilderRef,
+                           Val: ValueRef,
+                           DestTy: TypeRef,
+                           Name: *const c_char)
+                           -> ValueRef;
+    pub fn LLVMBuildSIToFP(B: BuilderRef,
+                           Val: ValueRef,
+                           DestTy: TypeRef,
+                           Name: *const c_char)
+                           -> ValueRef;
+    pub fn LLVMBuildFPTrunc(B: BuilderRef,
+                            Val: ValueRef,
+                            DestTy: TypeRef,
+                            Name: *const c_char)
+                            -> ValueRef;
+    pub fn LLVMBuildFPExt(B: BuilderRef,
+                          Val: ValueRef,
+                          DestTy: TypeRef,
+                          Name: *const c_char)
+                          -> ValueRef;
+    pub fn LLVMBuildPtrToInt(B: BuilderRef,
+                             Val: ValueRef,
+                             DestTy: TypeRef,
+                             Name: *const c_char)
+                             -> ValueRef;
+    pub fn LLVMBuildIntToPtr(B: BuilderRef,
+                             Val: ValueRef,
+                             DestTy: TypeRef,
+                             Name: *const c_char)
+                             -> ValueRef;
+    pub fn LLVMBuildBitCast(B: BuilderRef,
+                            Val: ValueRef,
+                            DestTy: TypeRef,
+                            Name: *const c_char)
+                            -> ValueRef;
+    pub fn LLVMBuildZExtOrBitCast(B: BuilderRef,
+                                  Val: ValueRef,
+                                  DestTy: TypeRef,
+                                  Name: *const c_char)
+                                  -> ValueRef;
+    pub fn LLVMBuildSExtOrBitCast(B: BuilderRef,
+                                  Val: ValueRef,
+                                  DestTy: TypeRef,
+                                  Name: *const c_char)
+                                  -> ValueRef;
+    pub fn LLVMBuildTruncOrBitCast(B: BuilderRef,
+                                   Val: ValueRef,
+                                   DestTy: TypeRef,
+                                   Name: *const c_char)
+                                   -> ValueRef;
+    pub fn LLVMBuildCast(B: BuilderRef,
+                         Op: Opcode,
+                         Val: ValueRef,
+                         DestTy: TypeRef,
+                         Name: *const c_char) -> ValueRef;
+    pub fn LLVMBuildPointerCast(B: BuilderRef,
+                                Val: ValueRef,
+                                DestTy: TypeRef,
+                                Name: *const c_char)
+                                -> ValueRef;
+    pub fn LLVMBuildIntCast(B: BuilderRef,
+                            Val: ValueRef,
+                            DestTy: TypeRef,
+                            Name: *const c_char)
+                            -> ValueRef;
+    pub fn LLVMBuildFPCast(B: BuilderRef,
+                           Val: ValueRef,
+                           DestTy: TypeRef,
+                           Name: *const c_char)
+                           -> ValueRef;
+
+    /* Comparisons */
+    pub fn LLVMBuildICmp(B: BuilderRef,
+                         Op: c_uint,
+                         LHS: ValueRef,
+                         RHS: ValueRef,
+                         Name: *const c_char)
+                         -> ValueRef;
+    pub fn LLVMBuildFCmp(B: BuilderRef,
+                         Op: c_uint,
+                         LHS: ValueRef,
+                         RHS: ValueRef,
+                         Name: *const c_char)
+                         -> ValueRef;
+
+    /* Miscellaneous instructions */
+    pub fn LLVMBuildPhi(B: BuilderRef, Ty: TypeRef, Name: *const c_char)
+                        -> ValueRef;
+    pub fn LLVMRustBuildCall(B: BuilderRef,
+                             Fn: ValueRef,
+                             Args: *const ValueRef,
+                             NumArgs: c_uint,
+                             Bundle: OperandBundleDefRef,
+                             Name: *const c_char)
+                             -> ValueRef;
+    pub fn LLVMBuildSelect(B: BuilderRef,
+                           If: ValueRef,
+                           Then: ValueRef,
+                           Else: ValueRef,
+                           Name: *const c_char)
+                           -> ValueRef;
+    pub fn LLVMBuildVAArg(B: BuilderRef,
+                          list: ValueRef,
+                          Ty: TypeRef,
+                          Name: *const c_char)
+                          -> ValueRef;
+    pub fn LLVMBuildExtractElement(B: BuilderRef,
+                                   VecVal: ValueRef,
+                                   Index: ValueRef,
+                                   Name: *const c_char)
+                                   -> ValueRef;
+    pub fn LLVMBuildInsertElement(B: BuilderRef,
+                                  VecVal: ValueRef,
+                                  EltVal: ValueRef,
+                                  Index: ValueRef,
+                                  Name: *const c_char)
+                                  -> ValueRef;
+    pub fn LLVMBuildShuffleVector(B: BuilderRef,
+                                  V1: ValueRef,
+                                  V2: ValueRef,
+                                  Mask: ValueRef,
+                                  Name: *const c_char)
+                                  -> ValueRef;
+    pub fn LLVMBuildExtractValue(B: BuilderRef,
+                                 AggVal: ValueRef,
+                                 Index: c_uint,
+                                 Name: *const c_char)
+                                 -> ValueRef;
+    pub fn LLVMBuildInsertValue(B: BuilderRef,
+                                AggVal: ValueRef,
+                                EltVal: ValueRef,
+                                Index: c_uint,
+                                Name: *const c_char)
+                                -> ValueRef;
+
+    pub fn LLVMBuildIsNull(B: BuilderRef, Val: ValueRef, Name: *const c_char)
+                           -> ValueRef;
+    pub fn LLVMBuildIsNotNull(B: BuilderRef, Val: ValueRef, Name: *const c_char)
+                              -> ValueRef;
+    pub fn LLVMBuildPtrDiff(B: BuilderRef,
+                            LHS: ValueRef,
+                            RHS: ValueRef,
+                            Name: *const c_char)
+                            -> ValueRef;
+
+    /* Atomic Operations */
+    pub fn LLVMRustBuildAtomicLoad(B: BuilderRef,
+                                   PointerVal: ValueRef,
+                                   Name: *const c_char,
+                                   Order: AtomicOrdering,
+                                   Alignment: c_uint)
+                                   -> ValueRef;
+
+    pub fn LLVMRustBuildAtomicStore(B: BuilderRef,
+                                    Val: ValueRef,
+                                    Ptr: ValueRef,
+                                    Order: AtomicOrdering,
+                                    Alignment: c_uint)
+                                    -> ValueRef;
+
+    pub fn LLVMRustBuildAtomicCmpXchg(B: BuilderRef,
+                                      LHS: ValueRef,
+                                      CMP: ValueRef,
+                                      RHS: ValueRef,
+                                      Order: AtomicOrdering,
+                                      FailureOrder: AtomicOrdering,
+                                      Weak: Bool)
+                                      -> ValueRef;
+
+    pub fn LLVMBuildAtomicRMW(B: BuilderRef,
+                              Op: AtomicRmwBinOp,
+                              LHS: ValueRef,
+                              RHS: ValueRef,
+                              Order: AtomicOrdering,
+                              SingleThreaded: Bool)
+                              -> ValueRef;
+
+    pub fn LLVMRustBuildAtomicFence(B: BuilderRef,
+                                    Order: AtomicOrdering,
+                                    Scope: SynchronizationScope);
+
+
+    /* Selected entries from the downcasts. */
+    pub fn LLVMIsATerminatorInst(Inst: ValueRef) -> ValueRef;
+    pub fn LLVMIsAStoreInst(Inst: ValueRef) -> ValueRef;
+
+    /// Writes a module to the specified path. Returns 0 on success.
+    pub fn LLVMWriteBitcodeToFile(M: ModuleRef, Path: *const c_char) -> c_int;
+
+    /// Creates target data from a target layout string.
+    pub fn LLVMCreateTargetData(StringRep: *const c_char) -> TargetDataRef;
+    /// Number of bytes clobbered when doing a Store to *T.
+    pub fn LLVMStoreSizeOfType(TD: TargetDataRef, Ty: TypeRef)
+                               -> c_ulonglong;
+
+    /// Number of bytes clobbered when doing a Store to *T.
+    pub fn LLVMSizeOfTypeInBits(TD: TargetDataRef, Ty: TypeRef)
+                                -> c_ulonglong;
+
+    /// Distance between successive elements in an array of T. Includes ABI padding.
+    pub fn LLVMABISizeOfType(TD: TargetDataRef, Ty: TypeRef) -> c_ulonglong;
+
+    /// Returns the preferred alignment of a type.
+    pub fn LLVMPreferredAlignmentOfType(TD: TargetDataRef, Ty: TypeRef)
+                                        -> c_uint;
+    /// Returns the minimum alignment of a type.
+    pub fn LLVMABIAlignmentOfType(TD: TargetDataRef, Ty: TypeRef)
+                                  -> c_uint;
+
+    /// Computes the byte offset of the indexed struct element for a
+    /// target.
+    pub fn LLVMOffsetOfElement(TD: TargetDataRef,
+                               StructTy: TypeRef,
+                               Element: c_uint)
+                               -> c_ulonglong;
+
+    /// Returns the minimum alignment of a type when part of a call frame.
+    pub fn LLVMCallFrameAlignmentOfType(TD: TargetDataRef, Ty: TypeRef)
+                                        -> c_uint;
+
+    /// Disposes target data.
+    pub fn LLVMDisposeTargetData(TD: TargetDataRef);
+
+    /// Creates a pass manager.
+    pub fn LLVMCreatePassManager() -> PassManagerRef;
+
+    /// Creates a function-by-function pass manager
+    pub fn LLVMCreateFunctionPassManagerForModule(M: ModuleRef)
+                                                  -> PassManagerRef;
+
+    /// Disposes a pass manager.
+    pub fn LLVMDisposePassManager(PM: PassManagerRef);
+
+    /// Runs a pass manager on a module.
+    pub fn LLVMRunPassManager(PM: PassManagerRef, M: ModuleRef) -> Bool;
+
+    /// Runs the function passes on the provided function.
+    pub fn LLVMRunFunctionPassManager(FPM: PassManagerRef, F: ValueRef)
+                                      -> Bool;
+
+    /// Initializes all the function passes scheduled in the manager
+    pub fn LLVMInitializeFunctionPassManager(FPM: PassManagerRef) -> Bool;
+
+    /// Finalizes all the function passes scheduled in the manager
+    pub fn LLVMFinalizeFunctionPassManager(FPM: PassManagerRef) -> Bool;
+
+    pub fn LLVMInitializePasses();
+
+    /// Adds a verification pass.
+    pub fn LLVMAddVerifierPass(PM: PassManagerRef);
+
+    pub fn LLVMAddGlobalOptimizerPass(PM: PassManagerRef);
+    pub fn LLVMAddIPSCCPPass(PM: PassManagerRef);
+    pub fn LLVMAddDeadArgEliminationPass(PM: PassManagerRef);
+    pub fn LLVMAddInstructionCombiningPass(PM: PassManagerRef);
+    pub fn LLVMAddCFGSimplificationPass(PM: PassManagerRef);
+    pub fn LLVMAddFunctionInliningPass(PM: PassManagerRef);
+    pub fn LLVMAddFunctionAttrsPass(PM: PassManagerRef);
+    pub fn LLVMAddScalarReplAggregatesPass(PM: PassManagerRef);
+    pub fn LLVMAddScalarReplAggregatesPassSSA(PM: PassManagerRef);
+    pub fn LLVMAddJumpThreadingPass(PM: PassManagerRef);
+    pub fn LLVMAddConstantPropagationPass(PM: PassManagerRef);
+    pub fn LLVMAddReassociatePass(PM: PassManagerRef);
+    pub fn LLVMAddLoopRotatePass(PM: PassManagerRef);
+    pub fn LLVMAddLICMPass(PM: PassManagerRef);
+    pub fn LLVMAddLoopUnswitchPass(PM: PassManagerRef);
+    pub fn LLVMAddLoopDeletionPass(PM: PassManagerRef);
+    pub fn LLVMAddLoopUnrollPass(PM: PassManagerRef);
+    pub fn LLVMAddGVNPass(PM: PassManagerRef);
+    pub fn LLVMAddMemCpyOptPass(PM: PassManagerRef);
+    pub fn LLVMAddSCCPPass(PM: PassManagerRef);
+    pub fn LLVMAddDeadStoreEliminationPass(PM: PassManagerRef);
+    pub fn LLVMAddStripDeadPrototypesPass(PM: PassManagerRef);
+    pub fn LLVMAddConstantMergePass(PM: PassManagerRef);
+    pub fn LLVMAddArgumentPromotionPass(PM: PassManagerRef);
+    pub fn LLVMAddTailCallEliminationPass(PM: PassManagerRef);
+    pub fn LLVMAddIndVarSimplifyPass(PM: PassManagerRef);
+    pub fn LLVMAddAggressiveDCEPass(PM: PassManagerRef);
+    pub fn LLVMAddGlobalDCEPass(PM: PassManagerRef);
+    pub fn LLVMAddCorrelatedValuePropagationPass(PM: PassManagerRef);
+    pub fn LLVMAddPruneEHPass(PM: PassManagerRef);
+    pub fn LLVMAddSimplifyLibCallsPass(PM: PassManagerRef);
+    pub fn LLVMAddLoopIdiomPass(PM: PassManagerRef);
+    pub fn LLVMAddEarlyCSEPass(PM: PassManagerRef);
+    pub fn LLVMAddTypeBasedAliasAnalysisPass(PM: PassManagerRef);
+    pub fn LLVMAddBasicAliasAnalysisPass(PM: PassManagerRef);
+
+    pub fn LLVMPassManagerBuilderCreate() -> PassManagerBuilderRef;
+    pub fn LLVMPassManagerBuilderDispose(PMB: PassManagerBuilderRef);
+    pub fn LLVMPassManagerBuilderSetOptLevel(PMB: PassManagerBuilderRef,
+                                             OptimizationLevel: c_uint);
+    pub fn LLVMPassManagerBuilderSetSizeLevel(PMB: PassManagerBuilderRef,
+                                              Value: Bool);
+    pub fn LLVMPassManagerBuilderSetDisableUnitAtATime(
+        PMB: PassManagerBuilderRef,
+        Value: Bool);
+    pub fn LLVMPassManagerBuilderSetDisableUnrollLoops(
+        PMB: PassManagerBuilderRef,
+        Value: Bool);
+    pub fn LLVMPassManagerBuilderSetDisableSimplifyLibCalls(
+        PMB: PassManagerBuilderRef,
+        Value: Bool);
+    pub fn LLVMPassManagerBuilderUseInlinerWithThreshold(
+        PMB: PassManagerBuilderRef,
+        threshold: c_uint);
+    pub fn LLVMPassManagerBuilderPopulateModulePassManager(
+        PMB: PassManagerBuilderRef,
+        PM: PassManagerRef);
+
+    pub fn LLVMPassManagerBuilderPopulateFunctionPassManager(
+        PMB: PassManagerBuilderRef,
+        PM: PassManagerRef);
+    pub fn LLVMPassManagerBuilderPopulateLTOPassManager(
+        PMB: PassManagerBuilderRef,
+        PM: PassManagerRef,
+        Internalize: Bool,
+        RunInliner: Bool);
+
+    /// Destroys a memory buffer.
+    pub fn LLVMDisposeMemoryBuffer(MemBuf: MemoryBufferRef);
+
+
+    /* Stuff that's in rustllvm/ because it's not upstream yet. */
+
+    /// Opens an object file.
+    pub fn LLVMCreateObjectFile(MemBuf: MemoryBufferRef) -> ObjectFileRef;
+    /// Closes an object file.
+    pub fn LLVMDisposeObjectFile(ObjFile: ObjectFileRef);
+
+    /// Enumerates the sections in an object file.
+    pub fn LLVMGetSections(ObjFile: ObjectFileRef) -> SectionIteratorRef;
+    /// Destroys a section iterator.
+    pub fn LLVMDisposeSectionIterator(SI: SectionIteratorRef);
+    /// Returns true if the section iterator is at the end of the section
+    /// list:
+    pub fn LLVMIsSectionIteratorAtEnd(ObjFile: ObjectFileRef,
+                                      SI: SectionIteratorRef)
+                                      -> Bool;
+    /// Moves the section iterator to point to the next section.
+    pub fn LLVMMoveToNextSection(SI: SectionIteratorRef);
+    /// Returns the current section size.
+    pub fn LLVMGetSectionSize(SI: SectionIteratorRef) -> c_ulonglong;
+    /// Returns the current section contents as a string buffer.
+    pub fn LLVMGetSectionContents(SI: SectionIteratorRef) -> *const c_char;
+
+    /// Reads the given file and returns it as a memory buffer. Use
+    /// LLVMDisposeMemoryBuffer() to get rid of it.
+    pub fn LLVMRustCreateMemoryBufferWithContentsOfFile(Path: *const c_char)
+                                                        -> MemoryBufferRef;
+    /// Borrows the contents of the memory buffer (doesn't copy it)
+    pub fn LLVMCreateMemoryBufferWithMemoryRange(InputData: *const c_char,
+                                                 InputDataLength: size_t,
+                                                 BufferName: *const c_char,
+                                                 RequiresNull: Bool)
+                                                 -> MemoryBufferRef;
+    pub fn LLVMCreateMemoryBufferWithMemoryRangeCopy(InputData: *const c_char,
+                                                     InputDataLength: size_t,
+                                                     BufferName: *const c_char)
+                                                     -> MemoryBufferRef;
+
+    pub fn LLVMIsMultithreaded() -> Bool;
+    pub fn LLVMStartMultithreaded() -> Bool;
+
+    /// Returns a string describing the last error caused by an LLVMRust* call.
+    pub fn LLVMRustGetLastError() -> *const c_char;
+
+    /// Print the pass timings since static dtors aren't picking them up.
+    pub fn LLVMRustPrintPassTimings();
+
+    pub fn LLVMStructCreateNamed(C: ContextRef, Name: *const c_char) -> TypeRef;
+
+    pub fn LLVMStructSetBody(StructTy: TypeRef,
+                             ElementTypes: *const TypeRef,
+                             ElementCount: c_uint,
+                             Packed: Bool);
+
+    pub fn LLVMConstNamedStruct(S: TypeRef,
+                                ConstantVals: *const ValueRef,
+                                Count: c_uint)
+                                -> ValueRef;
+
+    /// Enables LLVM debug output.
+    pub fn LLVMRustSetDebug(Enabled: c_int);
+
+    /// Prepares inline assembly.
+    pub fn LLVMRustInlineAsm(Ty: TypeRef,
+                             AsmString: *const c_char,
+                             Constraints: *const c_char,
+                             SideEffects: Bool,
+                             AlignStack: Bool,
+                             Dialect: AsmDialect)
+                             -> ValueRef;
+
+    pub fn LLVMRustDebugMetadataVersion() -> u32;
+    pub fn LLVMRustVersionMajor() -> u32;
+    pub fn LLVMRustVersionMinor() -> u32;
+
+    pub fn LLVMRustAddModuleFlag(M: ModuleRef,
+                                 name: *const c_char,
+                                 value: u32);
+
+    pub fn LLVMRustDIBuilderCreate(M: ModuleRef) -> DIBuilderRef;
+
+    pub fn LLVMRustDIBuilderDispose(Builder: DIBuilderRef);
+
+    pub fn LLVMRustDIBuilderFinalize(Builder: DIBuilderRef);
+
+    pub fn LLVMRustDIBuilderCreateCompileUnit(Builder: DIBuilderRef,
+                                              Lang: c_uint,
+                                              File: *const c_char,
+                                              Dir: *const c_char,
+                                              Producer: *const c_char,
+                                              isOptimized: bool,
+                                              Flags: *const c_char,
+                                              RuntimeVer: c_uint,
+                                              SplitName: *const c_char)
+                                              -> DIDescriptor;
+
+    pub fn LLVMRustDIBuilderCreateFile(Builder: DIBuilderRef,
+                                       Filename: *const c_char,
+                                       Directory: *const c_char)
+                                       -> DIFile;
+
+    pub fn LLVMRustDIBuilderCreateSubroutineType(Builder: DIBuilderRef,
+                                                 File: DIFile,
+                                                 ParameterTypes: DIArray)
+                                                 -> DICompositeType;
+
+    pub fn LLVMRustDIBuilderCreateFunction(Builder: DIBuilderRef,
+                                           Scope: DIDescriptor,
+                                           Name: *const c_char,
+                                           LinkageName: *const c_char,
+                                           File: DIFile,
+                                           LineNo: c_uint,
+                                           Ty: DIType,
+                                           isLocalToUnit: bool,
+                                           isDefinition: bool,
+                                           ScopeLine: c_uint,
+                                           Flags: c_uint,
+                                           isOptimized: bool,
+                                           Fn: ValueRef,
+                                           TParam: DIArray,
+                                           Decl: DIDescriptor)
+                                           -> DISubprogram;
+
+    pub fn LLVMRustDIBuilderCreateBasicType(Builder: DIBuilderRef,
+                                            Name: *const c_char,
+                                            SizeInBits: u64,
+                                            AlignInBits: u64,
+                                            Encoding: c_uint)
+                                            -> DIBasicType;
+
+    pub fn LLVMRustDIBuilderCreatePointerType(Builder: DIBuilderRef,
+                                          PointeeTy: DIType,
+                                          SizeInBits: u64,
+                                          AlignInBits: u64,
+                                          Name: *const c_char)
+                                          -> DIDerivedType;
+
+    pub fn LLVMRustDIBuilderCreateStructType(Builder: DIBuilderRef,
+                                             Scope: DIDescriptor,
+                                             Name: *const c_char,
+                                             File: DIFile,
+                                             LineNumber: c_uint,
+                                             SizeInBits: u64,
+                                             AlignInBits: u64,
+                                             Flags: c_uint,
+                                             DerivedFrom: DIType,
+                                             Elements: DIArray,
+                                             RunTimeLang: c_uint,
+                                             VTableHolder: DIType,
+                                             UniqueId: *const c_char)
+                                             -> DICompositeType;
+
+    pub fn LLVMRustDIBuilderCreateMemberType(Builder: DIBuilderRef,
+                                             Scope: DIDescriptor,
+                                             Name: *const c_char,
+                                             File: DIFile,
+                                             LineNo: c_uint,
+                                             SizeInBits: u64,
+                                             AlignInBits: u64,
+                                             OffsetInBits: u64,
+                                             Flags: c_uint,
+                                             Ty: DIType)
+                                             -> DIDerivedType;
+
+    pub fn LLVMRustDIBuilderCreateLexicalBlock(Builder: DIBuilderRef,
+                                               Scope: DIScope,
+                                               File: DIFile,
+                                               Line: c_uint,
+                                               Col: c_uint)
+                                               -> DILexicalBlock;
+
+    pub fn LLVMRustDIBuilderCreateStaticVariable(Builder: DIBuilderRef,
+                                                 Context: DIScope,
+                                                 Name: *const c_char,
+                                                 LinkageName: *const c_char,
+                                                 File: DIFile,
+                                                 LineNo: c_uint,
+                                                 Ty: DIType,
+                                                 isLocalToUnit: bool,
+                                                 Val: ValueRef,
+                                                 Decl: DIDescriptor)
+                                                 -> DIGlobalVariable;
+
+    pub fn LLVMRustDIBuilderCreateVariable(Builder: DIBuilderRef,
+                                           Tag: c_uint,
+                                           Scope: DIDescriptor,
+                                           Name: *const c_char,
+                                           File: DIFile,
+                                           LineNo: c_uint,
+                                           Ty: DIType,
+                                           AlwaysPreserve: bool,
+                                           Flags: c_uint,
+                                           AddrOps: *const i64,
+                                           AddrOpsCount: c_uint,
+                                           ArgNo: c_uint)
+                                           -> DIVariable;
+
+    pub fn LLVMRustDIBuilderCreateArrayType(Builder: DIBuilderRef,
+                                            Size: u64,
+                                            AlignInBits: u64,
+                                            Ty: DIType,
+                                            Subscripts: DIArray)
+                                            -> DIType;
+
+    pub fn LLVMRustDIBuilderCreateVectorType(Builder: DIBuilderRef,
+                                             Size: u64,
+                                             AlignInBits: u64,
+                                             Ty: DIType,
+                                             Subscripts: DIArray)
+                                             -> DIType;
+
+    pub fn LLVMRustDIBuilderGetOrCreateSubrange(Builder: DIBuilderRef,
+                                                Lo: i64,
+                                                Count: i64)
+                                                -> DISubrange;
+
+    pub fn LLVMRustDIBuilderGetOrCreateArray(Builder: DIBuilderRef,
+                                             Ptr: *const DIDescriptor,
+                                             Count: c_uint)
+                                             -> DIArray;
+
+    pub fn LLVMRustDIBuilderInsertDeclareAtEnd(Builder: DIBuilderRef,
+                                               Val: ValueRef,
+                                               VarInfo: DIVariable,
+                                               AddrOps: *const i64,
+                                               AddrOpsCount: c_uint,
+                                               DL: ValueRef,
+                                               InsertAtEnd: BasicBlockRef)
+                                               -> ValueRef;
+
+    pub fn LLVMRustDIBuilderInsertDeclareBefore(Builder: DIBuilderRef,
+                                                Val: ValueRef,
+                                                VarInfo: DIVariable,
+                                                AddrOps: *const i64,
+                                                AddrOpsCount: c_uint,
+                                                DL: ValueRef,
+                                                InsertBefore: ValueRef)
+                                                -> ValueRef;
+
+    pub fn LLVMRustDIBuilderCreateEnumerator(Builder: DIBuilderRef,
+                                             Name: *const c_char,
+                                             Val: u64)
+                                             -> DIEnumerator;
+
+    pub fn LLVMRustDIBuilderCreateEnumerationType(Builder: DIBuilderRef,
+                                                  Scope: DIScope,
+                                                  Name: *const c_char,
+                                                  File: DIFile,
+                                                  LineNumber: c_uint,
+                                                  SizeInBits: u64,
+                                                  AlignInBits: u64,
+                                                  Elements: DIArray,
+                                                  ClassType: DIType)
+                                                  -> DIType;
+
+    pub fn LLVMRustDIBuilderCreateUnionType(Builder: DIBuilderRef,
+                                            Scope: DIScope,
+                                            Name: *const c_char,
+                                            File: DIFile,
+                                            LineNumber: c_uint,
+                                            SizeInBits: u64,
+                                            AlignInBits: u64,
+                                            Flags: c_uint,
+                                            Elements: DIArray,
+                                            RunTimeLang: c_uint,
+                                            UniqueId: *const c_char)
+                                            -> DIType;
+
+    pub fn LLVMSetUnnamedAddr(GlobalVar: ValueRef, UnnamedAddr: Bool);
+
+    pub fn LLVMRustDIBuilderCreateTemplateTypeParameter(Builder: DIBuilderRef,
+                                                        Scope: DIScope,
+                                                        Name: *const c_char,
+                                                        Ty: DIType,
+                                                        File: DIFile,
+                                                        LineNo: c_uint,
+                                                        ColumnNo: c_uint)
+                                                        -> DITemplateTypeParameter;
+
+
+    pub fn LLVMRustDIBuilderCreateNameSpace(Builder: DIBuilderRef,
+                                            Scope: DIScope,
+                                            Name: *const c_char,
+                                            File: DIFile,
+                                            LineNo: c_uint)
+                                            -> DINameSpace;
+    pub fn LLVMRustDICompositeTypeSetTypeArray(Builder: DIBuilderRef,
+                                               CompositeType: DIType,
+                                               TypeArray: DIArray);
+
+
+    pub fn LLVMRustDIBuilderCreateDebugLocation(Context: ContextRef,
+                                                Line: c_uint,
+                                                Column: c_uint,
+                                                Scope: DIScope,
+                                                InlinedAt: MetadataRef)
+                                                -> ValueRef;
+    pub fn LLVMRustDIBuilderCreateOpDeref() -> i64;
+    pub fn LLVMRustDIBuilderCreateOpPlus() -> i64;
+
+    pub fn LLVMRustWriteTypeToString(Type: TypeRef, s: RustStringRef);
+    pub fn LLVMRustWriteValueToString(value_ref: ValueRef, s: RustStringRef);
+
+    pub fn LLVMIsAArgument(value_ref: ValueRef) -> ValueRef;
+
+    pub fn LLVMIsAAllocaInst(value_ref: ValueRef) -> ValueRef;
+    pub fn LLVMIsAConstantInt(value_ref: ValueRef) -> ValueRef;
+
+    pub fn LLVMRustPassKind(Pass: PassRef) -> PassKind;
+    pub fn LLVMRustFindAndCreatePass(Pass: *const c_char) -> PassRef;
+    pub fn LLVMRustAddPass(PM: PassManagerRef, Pass: PassRef);
+
+    pub fn LLVMRustHasFeature(T: TargetMachineRef,
+                              s: *const c_char) -> bool;
+
+    pub fn LLVMRustCreateTargetMachine(Triple: *const c_char,
+                                       CPU: *const c_char,
+                                       Features: *const c_char,
+                                       Model: CodeModel,
+                                       Reloc: RelocMode,
+                                       Level: CodeGenOptLevel,
+                                       UseSoftFP: bool,
+                                       PositionIndependentExecutable: bool,
+                                       FunctionSections: bool,
+                                       DataSections: bool) -> TargetMachineRef;
+    pub fn LLVMRustDisposeTargetMachine(T: TargetMachineRef);
+    pub fn LLVMRustAddAnalysisPasses(T: TargetMachineRef,
+                                     PM: PassManagerRef,
+                                     M: ModuleRef);
+    pub fn LLVMRustAddBuilderLibraryInfo(PMB: PassManagerBuilderRef,
+                                         M: ModuleRef,
+                                         DisableSimplifyLibCalls: bool);
+    pub fn LLVMRustConfigurePassManagerBuilder(PMB: PassManagerBuilderRef,
+                                               OptLevel: CodeGenOptLevel,
+                                               MergeFunctions: bool,
+                                               SLPVectorize: bool,
+                                               LoopVectorize: bool);
+    pub fn LLVMRustAddLibraryInfo(PM: PassManagerRef, M: ModuleRef,
+                                  DisableSimplifyLibCalls: bool);
+    pub fn LLVMRustRunFunctionPassManager(PM: PassManagerRef, M: ModuleRef);
+    pub fn LLVMRustWriteOutputFile(T: TargetMachineRef,
+                                   PM: PassManagerRef,
+                                   M: ModuleRef,
+                                   Output: *const c_char,
+                                   FileType: FileType)
+                                   -> LLVMRustResult;
+    pub fn LLVMRustPrintModule(PM: PassManagerRef,
+                               M: ModuleRef,
+                               Output: *const c_char);
+    pub fn LLVMRustSetLLVMOptions(Argc: c_int, Argv: *const *const c_char);
+    pub fn LLVMRustPrintPasses();
+    pub fn LLVMRustSetNormalizedTarget(M: ModuleRef, triple: *const c_char);
+    pub fn LLVMRustAddAlwaysInlinePass(P: PassManagerBuilderRef,
+                                       AddLifetimes: bool);
+    pub fn LLVMRustLinkInExternalBitcode(M: ModuleRef,
+                                         bc: *const c_char,
+                                         len: size_t) -> bool;
+    pub fn LLVMRustRunRestrictionPass(M: ModuleRef,
+                                      syms: *const *const c_char,
+                                      len: size_t);
+    pub fn LLVMRustMarkAllFunctionsNounwind(M: ModuleRef);
+
+    pub fn LLVMRustOpenArchive(path: *const c_char) -> ArchiveRef;
+    pub fn LLVMRustArchiveIteratorNew(AR: ArchiveRef) -> ArchiveIteratorRef;
+    pub fn LLVMRustArchiveIteratorNext(AIR: ArchiveIteratorRef) -> ArchiveChildRef;
+    pub fn LLVMRustArchiveChildName(ACR: ArchiveChildRef,
+                                    size: *mut size_t) -> *const c_char;
+    pub fn LLVMRustArchiveChildData(ACR: ArchiveChildRef,
+                                    size: *mut size_t) -> *const c_char;
+    pub fn LLVMRustArchiveChildFree(ACR: ArchiveChildRef);
+    pub fn LLVMRustArchiveIteratorFree(AIR: ArchiveIteratorRef);
+    pub fn LLVMRustDestroyArchive(AR: ArchiveRef);
+
+    pub fn LLVMRustGetSectionName(SI: SectionIteratorRef,
+                                  data: *mut *const c_char) -> size_t;
+
+    pub fn LLVMRustWriteTwineToString(T: TwineRef, s: RustStringRef);
+
+    pub fn LLVMContextSetDiagnosticHandler(C: ContextRef,
+                                           Handler: DiagnosticHandler,
+                                           DiagnosticContext: *mut c_void);
+
+    pub fn LLVMRustUnpackOptimizationDiagnostic(DI: DiagnosticInfoRef,
+                                                pass_name_out: *mut *const c_char,
+                                                function_out: *mut ValueRef,
+                                                debugloc_out: *mut DebugLocRef,
+                                                message_out: *mut TwineRef);
+    pub fn LLVMRustUnpackInlineAsmDiagnostic(DI: DiagnosticInfoRef,
+                                             cookie_out: *mut c_uint,
+                                             message_out: *mut TwineRef,
+                                             instruction_out: *mut ValueRef);
+
+    pub fn LLVMRustWriteDiagnosticInfoToString(DI: DiagnosticInfoRef,
+                                               s: RustStringRef);
+    pub fn LLVMGetDiagInfoSeverity(DI: DiagnosticInfoRef) -> DiagnosticSeverity;
+    pub fn LLVMRustGetDiagInfoKind(DI: DiagnosticInfoRef) -> DiagnosticKind;
+
+    pub fn LLVMRustWriteDebugLocToString(C: ContextRef,
+                                         DL: DebugLocRef,
+                                         s: RustStringRef);
+
+    pub fn LLVMRustSetInlineAsmDiagnosticHandler(C: ContextRef,
+                                                 H: InlineAsmDiagHandler,
+                                                 CX: *mut c_void);
+
+    pub fn LLVMRustWriteSMDiagnosticToString(d: SMDiagnosticRef, s: RustStringRef);
+
+    pub fn LLVMRustWriteArchive(Dst: *const c_char,
+                                NumMembers: size_t,
+                                Members: *const RustArchiveMemberRef,
+                                WriteSymbtab: bool,
+                                Kind: ArchiveKind) ->
+                                LLVMRustResult;
+    pub fn LLVMRustArchiveMemberNew(Filename: *const c_char,
+                                    Name: *const c_char,
+                                    Child: ArchiveChildRef) -> RustArchiveMemberRef;
+    pub fn LLVMRustArchiveMemberFree(Member: RustArchiveMemberRef);
+
+    pub fn LLVMRustSetDataLayoutFromTargetMachine(M: ModuleRef,
+                                                  TM: TargetMachineRef);
+    pub fn LLVMRustGetModuleDataLayout(M: ModuleRef) -> TargetDataRef;
+
+    pub fn LLVMRustBuildOperandBundleDef(Name: *const c_char,
+                                         Inputs: *const ValueRef,
+                                         NumInputs: c_uint)
+                                         -> OperandBundleDefRef;
+    pub fn LLVMRustFreeOperandBundleDef(Bundle: OperandBundleDefRef);
+
+    pub fn LLVMRustPositionBuilderAtStart(B: BuilderRef, BB: BasicBlockRef);
+
+    pub fn LLVMRustSetComdat(M: ModuleRef, V: ValueRef, Name: *const c_char);
+    pub fn LLVMRustUnsetComdat(V: ValueRef);
+    pub fn LLVMRustSetModulePIELevel(M: ModuleRef);
+}
+
+
+// LLVM requires symbols from this library, but apparently they're not printed
+// during llvm-config?
+#[cfg(windows)]
+#[link(name = "ole32")]
+extern {}
diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs
index e757201..6c4e1a5 100644
--- a/src/librustc_llvm/lib.rs
+++ b/src/librustc_llvm/lib.rs
@@ -33,157 +33,35 @@
 extern crate libc;
 #[macro_use] #[no_link] extern crate rustc_bitflags;
 
-pub use self::AttributeSet::*;
 pub use self::IntPredicate::*;
 pub use self::RealPredicate::*;
 pub use self::TypeKind::*;
-pub use self::AtomicBinOp::*;
-pub use self::AtomicOrdering::*;
-pub use self::SynchronizationScope::*;
-pub use self::FileType::*;
+pub use self::AtomicRmwBinOp::*;
 pub use self::MetadataType::*;
-pub use self::AsmDialect::*;
-pub use self::CodeGenOptLevel::*;
 pub use self::CodeGenOptSize::*;
-pub use self::RelocMode::*;
-pub use self::CodeGenModel::*;
 pub use self::DiagnosticKind::*;
 pub use self::CallConv::*;
-pub use self::Visibility::*;
 pub use self::DiagnosticSeverity::*;
 pub use self::Linkage::*;
-pub use self::DLLStorageClassTypes::*;
 
 use std::str::FromStr;
+use std::slice;
 use std::ffi::{CString, CStr};
 use std::cell::RefCell;
-use std::slice;
-use libc::{c_uint, c_ushort, uint64_t, c_int, size_t, c_char};
-use libc::{c_longlong, c_ulonglong, c_void};
-use debuginfo::{DIBuilderRef, DIDescriptor,
-                DIFile, DILexicalBlock, DISubprogram, DIType,
-                DIBasicType, DIDerivedType, DICompositeType, DIScope,
-                DIVariable, DIGlobalVariable, DIArray, DISubrange,
-                DITemplateTypeParameter, DIEnumerator, DINameSpace};
+use libc::{c_uint, c_char, size_t};
 
 pub mod archive_ro;
 pub mod diagnostic;
+pub mod ffi;
 
-pub type Opcode = u32;
-pub type Bool = c_uint;
+pub use ffi::*;
 
-pub const True: Bool = 1 as Bool;
-pub const False: Bool = 0 as Bool;
-
-// Consts for the LLVM CallConv type, pre-cast to usize.
-
-#[derive(Copy, Clone, PartialEq)]
-pub enum CallConv {
-    CCallConv = 0,
-    FastCallConv = 8,
-    ColdCallConv = 9,
-    X86StdcallCallConv = 64,
-    X86FastcallCallConv = 65,
-    X86_64_Win64 = 79,
-    X86_VectorCall = 80
-}
-
-#[derive(Copy, Clone)]
-pub enum Visibility {
-    LLVMDefaultVisibility = 0,
-    HiddenVisibility = 1,
-    ProtectedVisibility = 2,
-}
-
-// This enum omits the obsolete (and no-op) linkage types DLLImportLinkage,
-// DLLExportLinkage, GhostLinkage and LinkOnceODRAutoHideLinkage.
-// LinkerPrivateLinkage and LinkerPrivateWeakLinkage are not included either;
-// they've been removed in upstream LLVM commit r203866.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
-pub enum Linkage {
-    ExternalLinkage = 0,
-    AvailableExternallyLinkage = 1,
-    LinkOnceAnyLinkage = 2,
-    LinkOnceODRLinkage = 3,
-    WeakAnyLinkage = 5,
-    WeakODRLinkage = 6,
-    AppendingLinkage = 7,
-    InternalLinkage = 8,
-    PrivateLinkage = 9,
-    ExternalWeakLinkage = 12,
-    CommonLinkage = 14,
-}
-
-#[repr(C)]
-#[derive(Copy, Clone, Debug)]
-pub enum DiagnosticSeverity {
-    Error,
-    Warning,
-    Remark,
-    Note,
-}
-
-
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub enum DLLStorageClassTypes {
-    DefaultStorageClass = 0,
-    DLLImportStorageClass = 1,
-    DLLExportStorageClass = 2,
-}
-
-bitflags! {
-    #[derive(Default, Debug)]
-    flags Attribute : u64 {
-        const ZExt            = 1 << 0,
-        const SExt            = 1 << 1,
-        const NoReturn        = 1 << 2,
-        const InReg           = 1 << 3,
-        const StructRet       = 1 << 4,
-        const NoUnwind        = 1 << 5,
-        const NoAlias         = 1 << 6,
-        const ByVal           = 1 << 7,
-        const Nest            = 1 << 8,
-        const ReadNone        = 1 << 9,
-        const ReadOnly        = 1 << 10,
-        const NoInline        = 1 << 11,
-        const AlwaysInline    = 1 << 12,
-        const OptimizeForSize = 1 << 13,
-        const StackProtect    = 1 << 14,
-        const StackProtectReq = 1 << 15,
-        const NoCapture       = 1 << 21,
-        const NoRedZone       = 1 << 22,
-        const NoImplicitFloat = 1 << 23,
-        const Naked           = 1 << 24,
-        const InlineHint      = 1 << 25,
-        const ReturnsTwice    = 1 << 29,
-        const UWTable         = 1 << 30,
-        const NonLazyBind     = 1 << 31,
-
-        // Some of these are missing from the LLVM C API, the rest are
-        // present, but commented out, and preceded by the following warning:
-        // FIXME: These attributes are currently not included in the C API as
-        // a temporary measure until the API/ABI impact to the C API is understood
-        // and the path forward agreed upon.
-        const SanitizeAddress = 1 << 32,
-        const MinSize         = 1 << 33,
-        const NoDuplicate     = 1 << 34,
-        const StackProtectStrong = 1 << 35,
-        const SanitizeThread  = 1 << 36,
-        const SanitizeMemory  = 1 << 37,
-        const NoBuiltin       = 1 << 38,
-        const Returned        = 1 << 39,
-        const Cold            = 1 << 40,
-        const Builtin         = 1 << 41,
-        const OptimizeNone    = 1 << 42,
-        const InAlloca        = 1 << 43,
-        const NonNull         = 1 << 44,
-        const JumpTable       = 1 << 45,
-        const Convergent      = 1 << 46,
-        const SafeStack       = 1 << 47,
-        const NoRecurse       = 1 << 48,
-        const InaccessibleMemOnly         = 1 << 49,
-        const InaccessibleMemOrArgMemOnly = 1 << 50,
+impl LLVMRustResult {
+    pub fn into_result(self) -> Result<(), ()> {
+        match self {
+            LLVMRustResult::Success => Ok(()),
+            LLVMRustResult::Failure => Err(()),
+        }
     }
 }
 
@@ -214,167 +92,64 @@
         self
     }
 
-    pub fn apply_llfn(&self, idx: usize, llfn: ValueRef) {
+    pub fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef) {
         unsafe {
-            LLVMAddFunctionAttribute(llfn, idx as c_uint, self.regular.bits());
+            self.regular.apply_llfn(idx, llfn);
             if self.dereferenceable_bytes != 0 {
-                LLVMAddDereferenceableAttr(llfn, idx as c_uint,
-                                           self.dereferenceable_bytes);
+                LLVMRustAddDereferenceableAttr(
+                    llfn,
+                    idx.as_uint(),
+                    self.dereferenceable_bytes);
             }
         }
     }
 
-    pub fn apply_callsite(&self, idx: usize, callsite: ValueRef) {
+    pub fn apply_callsite(&self, idx: AttributePlace, callsite: ValueRef) {
         unsafe {
-            LLVMAddCallSiteAttribute(callsite, idx as c_uint, self.regular.bits());
+            self.regular.apply_callsite(idx, callsite);
             if self.dereferenceable_bytes != 0 {
-                LLVMAddDereferenceableCallSiteAttr(callsite, idx as c_uint,
-                                                   self.dereferenceable_bytes);
+                LLVMRustAddDereferenceableCallSiteAttr(
+                    callsite,
+                    idx.as_uint(),
+                    self.dereferenceable_bytes);
             }
         }
     }
 }
 
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub enum AttributeSet {
-    ReturnIndex = 0,
-    FunctionIndex = !0
-}
-
-// enum for the LLVM IntPredicate type
-#[derive(Copy, Clone)]
-pub enum IntPredicate {
-    IntEQ = 32,
-    IntNE = 33,
-    IntUGT = 34,
-    IntUGE = 35,
-    IntULT = 36,
-    IntULE = 37,
-    IntSGT = 38,
-    IntSGE = 39,
-    IntSLT = 40,
-    IntSLE = 41,
-}
-
-// enum for the LLVM RealPredicate type
-#[derive(Copy, Clone)]
-pub enum RealPredicate {
-    RealPredicateFalse = 0,
-    RealOEQ = 1,
-    RealOGT = 2,
-    RealOGE = 3,
-    RealOLT = 4,
-    RealOLE = 5,
-    RealONE = 6,
-    RealORD = 7,
-    RealUNO = 8,
-    RealUEQ = 9,
-    RealUGT = 10,
-    RealUGE = 11,
-    RealULT = 12,
-    RealULE = 13,
-    RealUNE = 14,
-    RealPredicateTrue = 15,
-}
-
-// The LLVM TypeKind type - must stay in sync with the def of
-// LLVMTypeKind in llvm/include/llvm-c/Core.h
-#[derive(Copy, Clone, PartialEq, Debug)]
-#[repr(C)]
-pub enum TypeKind {
-    Void      = 0,
-    Half      = 1,
-    Float     = 2,
-    Double    = 3,
-    X86_FP80  = 4,
-    FP128     = 5,
-    PPC_FP128 = 6,
-    Label     = 7,
-    Integer   = 8,
-    Function  = 9,
-    Struct    = 10,
-    Array     = 11,
-    Pointer   = 12,
-    Vector    = 13,
-    Metadata  = 14,
-    X86_MMX   = 15,
+pub fn AddFunctionAttrStringValue(
+    llfn: ValueRef,
+    idx: AttributePlace,
+    attr: &'static str,
+    value: &'static str
+) {
+    unsafe {
+        LLVMRustAddFunctionAttrStringValue(
+            llfn,
+            idx.as_uint(),
+            attr.as_ptr() as *const _,
+            value.as_ptr() as *const _)
+    }
 }
 
 #[repr(C)]
 #[derive(Copy, Clone)]
-pub enum AtomicBinOp {
-    AtomicXchg = 0,
-    AtomicAdd  = 1,
-    AtomicSub  = 2,
-    AtomicAnd  = 3,
-    AtomicNand = 4,
-    AtomicOr   = 5,
-    AtomicXor  = 6,
-    AtomicMax  = 7,
-    AtomicMin  = 8,
-    AtomicUMax = 9,
-    AtomicUMin = 10,
+pub enum AttributePlace {
+    Argument(u32),
+    Function,
 }
 
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub enum AtomicOrdering {
-    NotAtomic = 0,
-    Unordered = 1,
-    Monotonic = 2,
-    // Consume = 3,  // Not specified yet.
-    Acquire = 4,
-    Release = 5,
-    AcquireRelease = 6,
-    SequentiallyConsistent = 7
-}
+impl AttributePlace {
+    pub fn ReturnValue() -> Self {
+        AttributePlace::Argument(0)
+    }
 
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub enum SynchronizationScope {
-    SingleThread = 0,
-    CrossThread = 1
-}
-
-// Consts for the LLVMCodeGenFileType type (in include/llvm/c/TargetMachine.h)
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub enum FileType {
-    AssemblyFileType = 0,
-    ObjectFileType = 1
-}
-
-#[derive(Copy, Clone)]
-pub enum MetadataType {
-    MD_dbg = 0,
-    MD_tbaa = 1,
-    MD_prof = 2,
-    MD_fpmath = 3,
-    MD_range = 4,
-    MD_tbaa_struct = 5,
-    MD_invariant_load = 6,
-    MD_alias_scope = 7,
-    MD_noalias = 8,
-    MD_nontemporal = 9,
-    MD_mem_parallel_loop_access = 10,
-    MD_nonnull = 11,
-}
-
-// Inline Asm Dialect
-#[derive(Copy, Clone)]
-pub enum AsmDialect {
-    AD_ATT   = 0,
-    AD_Intel = 1
-}
-
-#[derive(Copy, Clone, PartialEq)]
-#[repr(C)]
-pub enum CodeGenOptLevel {
-    CodeGenLevelNone = 0,
-    CodeGenLevelLess = 1,
-    CodeGenLevelDefault = 2,
-    CodeGenLevelAggressive = 3,
+    fn as_uint(self) -> c_uint {
+        match self {
+            AttributePlace::Function => !0,
+            AttributePlace::Argument(i) => i,
+        }
+    }
 }
 
 #[derive(Copy, Clone, PartialEq)]
@@ -385,48 +160,6 @@
     CodeGenOptSizeAggressive = 2,
 }
 
-#[derive(Copy, Clone, PartialEq)]
-#[repr(C)]
-pub enum RelocMode {
-    RelocDefault = 0,
-    RelocStatic = 1,
-    RelocPIC = 2,
-    RelocDynamicNoPic = 3,
-}
-
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub enum CodeGenModel {
-    CodeModelDefault = 0,
-    CodeModelJITDefault = 1,
-    CodeModelSmall = 2,
-    CodeModelKernel = 3,
-    CodeModelMedium = 4,
-    CodeModelLarge = 5,
-}
-
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub enum DiagnosticKind {
-    DK_InlineAsm = 0,
-    DK_StackSize,
-    DK_DebugMetadataVersion,
-    DK_SampleProfile,
-    DK_OptimizationRemark,
-    DK_OptimizationRemarkMissed,
-    DK_OptimizationRemarkAnalysis,
-    DK_OptimizationFailure,
-}
-
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub enum ArchiveKind {
-    K_GNU,
-    K_MIPS64,
-    K_BSD,
-    K_COFF,
-}
-
 impl FromStr for ArchiveKind {
     type Err = ();
 
@@ -441,1728 +174,22 @@
     }
 }
 
-/// Represents the different LLVM passes Rust supports
-#[derive(Copy, Clone, PartialEq, Debug)]
-#[repr(C)]
-pub enum SupportedPassKind {
-    Function,
-    Module,
-    Unsupported,
+#[allow(missing_copy_implementations)]
+pub enum RustString_opaque {}
+pub type RustStringRef = *mut RustString_opaque;
+type RustStringRepr = *mut RefCell<Vec<u8>>;
+
+/// Appending to a Rust string -- used by raw_rust_string_ostream.
+#[no_mangle]
+pub unsafe extern "C" fn rust_llvm_string_write_impl(sr: RustStringRef,
+                                                     ptr: *const c_char,
+                                                     size: size_t) {
+    let slice = slice::from_raw_parts(ptr as *const u8, size as usize);
+
+    let sr = sr as RustStringRepr;
+    (*sr).borrow_mut().extend_from_slice(slice);
 }
 
-// Opaque pointer types
-#[allow(missing_copy_implementations)]
-pub enum Module_opaque {}
-pub type ModuleRef = *mut Module_opaque;
-#[allow(missing_copy_implementations)]
-pub enum Context_opaque {}
-pub type ContextRef = *mut Context_opaque;
-#[allow(missing_copy_implementations)]
-pub enum Type_opaque {}
-pub type TypeRef = *mut Type_opaque;
-#[allow(missing_copy_implementations)]
-pub enum Value_opaque {}
-pub type ValueRef = *mut Value_opaque;
-#[allow(missing_copy_implementations)]
-pub enum Metadata_opaque {}
-pub type MetadataRef = *mut Metadata_opaque;
-#[allow(missing_copy_implementations)]
-pub enum BasicBlock_opaque {}
-pub type BasicBlockRef = *mut BasicBlock_opaque;
-#[allow(missing_copy_implementations)]
-pub enum Builder_opaque {}
-pub type BuilderRef = *mut Builder_opaque;
-#[allow(missing_copy_implementations)]
-pub enum ExecutionEngine_opaque {}
-pub type ExecutionEngineRef = *mut ExecutionEngine_opaque;
-#[allow(missing_copy_implementations)]
-pub enum MemoryBuffer_opaque {}
-pub type MemoryBufferRef = *mut MemoryBuffer_opaque;
-#[allow(missing_copy_implementations)]
-pub enum PassManager_opaque {}
-pub type PassManagerRef = *mut PassManager_opaque;
-#[allow(missing_copy_implementations)]
-pub enum PassManagerBuilder_opaque {}
-pub type PassManagerBuilderRef = *mut PassManagerBuilder_opaque;
-#[allow(missing_copy_implementations)]
-pub enum Use_opaque {}
-pub type UseRef = *mut Use_opaque;
-#[allow(missing_copy_implementations)]
-pub enum TargetData_opaque {}
-pub type TargetDataRef = *mut TargetData_opaque;
-#[allow(missing_copy_implementations)]
-pub enum ObjectFile_opaque {}
-pub type ObjectFileRef = *mut ObjectFile_opaque;
-#[allow(missing_copy_implementations)]
-pub enum SectionIterator_opaque {}
-pub type SectionIteratorRef = *mut SectionIterator_opaque;
-#[allow(missing_copy_implementations)]
-pub enum Pass_opaque {}
-pub type PassRef = *mut Pass_opaque;
-#[allow(missing_copy_implementations)]
-pub enum TargetMachine_opaque {}
-pub type TargetMachineRef = *mut TargetMachine_opaque;
-pub enum Archive_opaque {}
-pub type ArchiveRef = *mut Archive_opaque;
-pub enum ArchiveIterator_opaque {}
-pub type ArchiveIteratorRef = *mut ArchiveIterator_opaque;
-pub enum ArchiveChild_opaque {}
-pub type ArchiveChildRef = *mut ArchiveChild_opaque;
-#[allow(missing_copy_implementations)]
-pub enum Twine_opaque {}
-pub type TwineRef = *mut Twine_opaque;
-#[allow(missing_copy_implementations)]
-pub enum DiagnosticInfo_opaque {}
-pub type DiagnosticInfoRef = *mut DiagnosticInfo_opaque;
-#[allow(missing_copy_implementations)]
-pub enum DebugLoc_opaque {}
-pub type DebugLocRef = *mut DebugLoc_opaque;
-#[allow(missing_copy_implementations)]
-pub enum SMDiagnostic_opaque {}
-pub type SMDiagnosticRef = *mut SMDiagnostic_opaque;
-#[allow(missing_copy_implementations)]
-pub enum RustArchiveMember_opaque {}
-pub type RustArchiveMemberRef = *mut RustArchiveMember_opaque;
-#[allow(missing_copy_implementations)]
-pub enum OperandBundleDef_opaque {}
-pub type OperandBundleDefRef = *mut OperandBundleDef_opaque;
-
-pub type DiagnosticHandler = unsafe extern "C" fn(DiagnosticInfoRef, *mut c_void);
-pub type InlineAsmDiagHandler = unsafe extern "C" fn(SMDiagnosticRef, *const c_void, c_uint);
-
-pub mod debuginfo {
-    pub use self::DIDescriptorFlags::*;
-    use super::{MetadataRef};
-
-    #[allow(missing_copy_implementations)]
-    pub enum DIBuilder_opaque {}
-    pub type DIBuilderRef = *mut DIBuilder_opaque;
-
-    pub type DIDescriptor = MetadataRef;
-    pub type DIScope = DIDescriptor;
-    pub type DILocation = DIDescriptor;
-    pub type DIFile = DIScope;
-    pub type DILexicalBlock = DIScope;
-    pub type DISubprogram = DIScope;
-    pub type DINameSpace = DIScope;
-    pub type DIType = DIDescriptor;
-    pub type DIBasicType = DIType;
-    pub type DIDerivedType = DIType;
-    pub type DICompositeType = DIDerivedType;
-    pub type DIVariable = DIDescriptor;
-    pub type DIGlobalVariable = DIDescriptor;
-    pub type DIArray = DIDescriptor;
-    pub type DISubrange = DIDescriptor;
-    pub type DIEnumerator = DIDescriptor;
-    pub type DITemplateTypeParameter = DIDescriptor;
-
-    #[derive(Copy, Clone)]
-    pub enum DIDescriptorFlags {
-      FlagPrivate            = 1 << 0,
-      FlagProtected          = 1 << 1,
-      FlagFwdDecl            = 1 << 2,
-      FlagAppleBlock         = 1 << 3,
-      FlagBlockByrefStruct   = 1 << 4,
-      FlagVirtual            = 1 << 5,
-      FlagArtificial         = 1 << 6,
-      FlagExplicit           = 1 << 7,
-      FlagPrototyped         = 1 << 8,
-      FlagObjcClassComplete  = 1 << 9,
-      FlagObjectPointer      = 1 << 10,
-      FlagVector             = 1 << 11,
-      FlagStaticMember       = 1 << 12,
-      FlagIndirectVariable   = 1 << 13,
-      FlagLValueReference    = 1 << 14,
-      FlagRValueReference    = 1 << 15
-    }
-}
-
-
-// Link to our native llvm bindings (things that we need to use the C++ api
-// for) and because llvm is written in C++ we need to link against libstdc++
-//
-// You'll probably notice that there is an omission of all LLVM libraries
-// from this location. This is because the set of LLVM libraries that we
-// link to is mostly defined by LLVM, and the `llvm-config` tool is used to
-// figure out the exact set of libraries. To do this, the build system
-// generates an llvmdeps.rs file next to this one which will be
-// automatically updated whenever LLVM is updated to include an up-to-date
-// set of the libraries we need to link to LLVM for.
-#[link(name = "rustllvm", kind = "static")]
-#[cfg(not(cargobuild))]
-extern {}
-
-#[linked_from = "rustllvm"] // not quite true but good enough
-extern {
-    /* Create and destroy contexts. */
-    pub fn LLVMContextCreate() -> ContextRef;
-    pub fn LLVMContextDispose(C: ContextRef);
-    pub fn LLVMGetMDKindIDInContext(C: ContextRef,
-                                    Name: *const c_char,
-                                    SLen: c_uint)
-                                    -> c_uint;
-
-    /* Create and destroy modules. */
-    pub fn LLVMModuleCreateWithNameInContext(ModuleID: *const c_char,
-                                             C: ContextRef)
-                                             -> ModuleRef;
-    pub fn LLVMGetModuleContext(M: ModuleRef) -> ContextRef;
-    pub fn LLVMCloneModule(M: ModuleRef) -> ModuleRef;
-    pub fn LLVMDisposeModule(M: ModuleRef);
-
-    /// Data layout. See Module::getDataLayout.
-    pub fn LLVMGetDataLayout(M: ModuleRef) -> *const c_char;
-    pub fn LLVMSetDataLayout(M: ModuleRef, Triple: *const c_char);
-
-    /// Target triple. See Module::getTargetTriple.
-    pub fn LLVMGetTarget(M: ModuleRef) -> *const c_char;
-    pub fn LLVMSetTarget(M: ModuleRef, Triple: *const c_char);
-
-    /// See Module::dump.
-    pub fn LLVMDumpModule(M: ModuleRef);
-
-    /// See Module::setModuleInlineAsm.
-    pub fn LLVMSetModuleInlineAsm(M: ModuleRef, Asm: *const c_char);
-
-    /// See llvm::LLVMTypeKind::getTypeID.
-    pub fn LLVMGetTypeKind(Ty: TypeRef) -> TypeKind;
-
-    /// See llvm::LLVMType::getContext.
-    pub fn LLVMGetTypeContext(Ty: TypeRef) -> ContextRef;
-
-    /* Operations on integer types */
-    pub fn LLVMInt1TypeInContext(C: ContextRef) -> TypeRef;
-    pub fn LLVMInt8TypeInContext(C: ContextRef) -> TypeRef;
-    pub fn LLVMInt16TypeInContext(C: ContextRef) -> TypeRef;
-    pub fn LLVMInt32TypeInContext(C: ContextRef) -> TypeRef;
-    pub fn LLVMInt64TypeInContext(C: ContextRef) -> TypeRef;
-    pub fn LLVMIntTypeInContext(C: ContextRef, NumBits: c_uint)
-                                -> TypeRef;
-
-    pub fn LLVMGetIntTypeWidth(IntegerTy: TypeRef) -> c_uint;
-
-    /* Operations on real types */
-    pub fn LLVMFloatTypeInContext(C: ContextRef) -> TypeRef;
-    pub fn LLVMDoubleTypeInContext(C: ContextRef) -> TypeRef;
-    pub fn LLVMX86FP80TypeInContext(C: ContextRef) -> TypeRef;
-    pub fn LLVMFP128TypeInContext(C: ContextRef) -> TypeRef;
-    pub fn LLVMPPCFP128TypeInContext(C: ContextRef) -> TypeRef;
-
-    /* Operations on function types */
-    pub fn LLVMFunctionType(ReturnType: TypeRef,
-                            ParamTypes: *const TypeRef,
-                            ParamCount: c_uint,
-                            IsVarArg: Bool)
-                            -> TypeRef;
-    pub fn LLVMIsFunctionVarArg(FunctionTy: TypeRef) -> Bool;
-    pub fn LLVMGetReturnType(FunctionTy: TypeRef) -> TypeRef;
-    pub fn LLVMCountParamTypes(FunctionTy: TypeRef) -> c_uint;
-    pub fn LLVMGetParamTypes(FunctionTy: TypeRef, Dest: *mut TypeRef);
-
-    /* Operations on struct types */
-    pub fn LLVMStructTypeInContext(C: ContextRef,
-                                   ElementTypes: *const TypeRef,
-                                   ElementCount: c_uint,
-                                   Packed: Bool)
-                                   -> TypeRef;
-    pub fn LLVMCountStructElementTypes(StructTy: TypeRef) -> c_uint;
-    pub fn LLVMGetStructElementTypes(StructTy: TypeRef,
-                                     Dest: *mut TypeRef);
-    pub fn LLVMIsPackedStruct(StructTy: TypeRef) -> Bool;
-
-    /* Operations on array, pointer, and vector types (sequence types) */
-    pub fn LLVMRustArrayType(ElementType: TypeRef, ElementCount: u64) -> TypeRef;
-    pub fn LLVMPointerType(ElementType: TypeRef, AddressSpace: c_uint)
-                           -> TypeRef;
-    pub fn LLVMVectorType(ElementType: TypeRef, ElementCount: c_uint)
-                          -> TypeRef;
-
-    pub fn LLVMGetElementType(Ty: TypeRef) -> TypeRef;
-    pub fn LLVMGetArrayLength(ArrayTy: TypeRef) -> c_uint;
-    pub fn LLVMGetPointerAddressSpace(PointerTy: TypeRef) -> c_uint;
-    pub fn LLVMGetPointerToGlobal(EE: ExecutionEngineRef, V: ValueRef)
-                                  -> *const c_void;
-    pub fn LLVMGetVectorSize(VectorTy: TypeRef) -> c_uint;
-
-    /* Operations on other types */
-    pub fn LLVMVoidTypeInContext(C: ContextRef) -> TypeRef;
-    pub fn LLVMLabelTypeInContext(C: ContextRef) -> TypeRef;
-    pub fn LLVMMetadataTypeInContext(C: ContextRef) -> TypeRef;
-
-    /* Operations on all values */
-    pub fn LLVMTypeOf(Val: ValueRef) -> TypeRef;
-    pub fn LLVMGetValueName(Val: ValueRef) -> *const c_char;
-    pub fn LLVMSetValueName(Val: ValueRef, Name: *const c_char);
-    pub fn LLVMDumpValue(Val: ValueRef);
-    pub fn LLVMReplaceAllUsesWith(OldVal: ValueRef, NewVal: ValueRef);
-    pub fn LLVMHasMetadata(Val: ValueRef) -> c_int;
-    pub fn LLVMGetMetadata(Val: ValueRef, KindID: c_uint) -> ValueRef;
-    pub fn LLVMSetMetadata(Val: ValueRef, KindID: c_uint, Node: ValueRef);
-
-    /* Operations on Uses */
-    pub fn LLVMGetFirstUse(Val: ValueRef) -> UseRef;
-    pub fn LLVMGetNextUse(U: UseRef) -> UseRef;
-    pub fn LLVMGetUser(U: UseRef) -> ValueRef;
-    pub fn LLVMGetUsedValue(U: UseRef) -> ValueRef;
-
-    /* Operations on Users */
-    pub fn LLVMGetNumOperands(Val: ValueRef) -> c_int;
-    pub fn LLVMGetOperand(Val: ValueRef, Index: c_uint) -> ValueRef;
-    pub fn LLVMSetOperand(Val: ValueRef, Index: c_uint, Op: ValueRef);
-
-    /* Operations on constants of any type */
-    pub fn LLVMConstNull(Ty: TypeRef) -> ValueRef;
-    /* all zeroes */
-    pub fn LLVMConstAllOnes(Ty: TypeRef) -> ValueRef;
-    pub fn LLVMConstICmp(Pred: c_ushort, V1: ValueRef, V2: ValueRef)
-                         -> ValueRef;
-    pub fn LLVMConstFCmp(Pred: c_ushort, V1: ValueRef, V2: ValueRef)
-                         -> ValueRef;
-    /* only for isize/vector */
-    pub fn LLVMGetUndef(Ty: TypeRef) -> ValueRef;
-    pub fn LLVMIsConstant(Val: ValueRef) -> Bool;
-    pub fn LLVMIsNull(Val: ValueRef) -> Bool;
-    pub fn LLVMIsUndef(Val: ValueRef) -> Bool;
-    pub fn LLVMConstPointerNull(Ty: TypeRef) -> ValueRef;
-
-    /* Operations on metadata */
-    pub fn LLVMMDStringInContext(C: ContextRef,
-                                 Str: *const c_char,
-                                 SLen: c_uint)
-                                 -> ValueRef;
-    pub fn LLVMMDNodeInContext(C: ContextRef,
-                               Vals: *const ValueRef,
-                               Count: c_uint)
-                               -> ValueRef;
-    pub fn LLVMAddNamedMetadataOperand(M: ModuleRef,
-                                       Str: *const c_char,
-                                       Val: ValueRef);
-
-    /* Operations on scalar constants */
-    pub fn LLVMConstInt(IntTy: TypeRef, N: c_ulonglong, SignExtend: Bool)
-                        -> ValueRef;
-    pub fn LLVMConstIntOfString(IntTy: TypeRef, Text: *const c_char, Radix: u8)
-                                -> ValueRef;
-    pub fn LLVMConstIntOfStringAndSize(IntTy: TypeRef,
-                                       Text: *const c_char,
-                                       SLen: c_uint,
-                                       Radix: u8)
-                                       -> ValueRef;
-    pub fn LLVMConstReal(RealTy: TypeRef, N: f64) -> ValueRef;
-    pub fn LLVMConstRealOfString(RealTy: TypeRef, Text: *const c_char)
-                                 -> ValueRef;
-    pub fn LLVMConstRealOfStringAndSize(RealTy: TypeRef,
-                                        Text: *const c_char,
-                                        SLen: c_uint)
-                                        -> ValueRef;
-    pub fn LLVMConstIntGetZExtValue(ConstantVal: ValueRef) -> c_ulonglong;
-    pub fn LLVMConstIntGetSExtValue(ConstantVal: ValueRef) -> c_longlong;
-
-
-    /* Operations on composite constants */
-    pub fn LLVMConstStringInContext(C: ContextRef,
-                                    Str: *const c_char,
-                                    Length: c_uint,
-                                    DontNullTerminate: Bool)
-                                    -> ValueRef;
-    pub fn LLVMConstStructInContext(C: ContextRef,
-                                    ConstantVals: *const ValueRef,
-                                    Count: c_uint,
-                                    Packed: Bool)
-                                    -> ValueRef;
-
-    pub fn LLVMConstArray(ElementTy: TypeRef,
-                          ConstantVals: *const ValueRef,
-                          Length: c_uint)
-                          -> ValueRef;
-    pub fn LLVMConstVector(ScalarConstantVals: *const ValueRef, Size: c_uint)
-                           -> ValueRef;
-
-    /* Constant expressions */
-    pub fn LLVMAlignOf(Ty: TypeRef) -> ValueRef;
-    pub fn LLVMSizeOf(Ty: TypeRef) -> ValueRef;
-    pub fn LLVMConstNeg(ConstantVal: ValueRef) -> ValueRef;
-    pub fn LLVMConstNSWNeg(ConstantVal: ValueRef) -> ValueRef;
-    pub fn LLVMConstNUWNeg(ConstantVal: ValueRef) -> ValueRef;
-    pub fn LLVMConstFNeg(ConstantVal: ValueRef) -> ValueRef;
-    pub fn LLVMConstNot(ConstantVal: ValueRef) -> ValueRef;
-    pub fn LLVMConstAdd(LHSConstant: ValueRef, RHSConstant: ValueRef)
-                        -> ValueRef;
-    pub fn LLVMConstNSWAdd(LHSConstant: ValueRef, RHSConstant: ValueRef)
-                           -> ValueRef;
-    pub fn LLVMConstNUWAdd(LHSConstant: ValueRef, RHSConstant: ValueRef)
-                           -> ValueRef;
-    pub fn LLVMConstFAdd(LHSConstant: ValueRef, RHSConstant: ValueRef)
-                         -> ValueRef;
-    pub fn LLVMConstSub(LHSConstant: ValueRef, RHSConstant: ValueRef)
-                        -> ValueRef;
-    pub fn LLVMConstNSWSub(LHSConstant: ValueRef, RHSConstant: ValueRef)
-                           -> ValueRef;
-    pub fn LLVMConstNUWSub(LHSConstant: ValueRef, RHSConstant: ValueRef)
-                           -> ValueRef;
-    pub fn LLVMConstFSub(LHSConstant: ValueRef, RHSConstant: ValueRef)
-                         -> ValueRef;
-    pub fn LLVMConstMul(LHSConstant: ValueRef, RHSConstant: ValueRef)
-                        -> ValueRef;
-    pub fn LLVMConstNSWMul(LHSConstant: ValueRef, RHSConstant: ValueRef)
-                           -> ValueRef;
-    pub fn LLVMConstNUWMul(LHSConstant: ValueRef, RHSConstant: ValueRef)
-                           -> ValueRef;
-    pub fn LLVMConstFMul(LHSConstant: ValueRef, RHSConstant: ValueRef)
-                         -> ValueRef;
-    pub fn LLVMConstUDiv(LHSConstant: ValueRef, RHSConstant: ValueRef)
-                         -> ValueRef;
-    pub fn LLVMConstSDiv(LHSConstant: ValueRef, RHSConstant: ValueRef)
-                         -> ValueRef;
-    pub fn LLVMConstExactSDiv(LHSConstant: ValueRef,
-                              RHSConstant: ValueRef)
-                              -> ValueRef;
-    pub fn LLVMConstFDiv(LHSConstant: ValueRef, RHSConstant: ValueRef)
-                         -> ValueRef;
-    pub fn LLVMConstURem(LHSConstant: ValueRef, RHSConstant: ValueRef)
-                         -> ValueRef;
-    pub fn LLVMConstSRem(LHSConstant: ValueRef, RHSConstant: ValueRef)
-                         -> ValueRef;
-    pub fn LLVMConstFRem(LHSConstant: ValueRef, RHSConstant: ValueRef)
-                         -> ValueRef;
-    pub fn LLVMConstAnd(LHSConstant: ValueRef, RHSConstant: ValueRef)
-                        -> ValueRef;
-    pub fn LLVMConstOr(LHSConstant: ValueRef, RHSConstant: ValueRef)
-                       -> ValueRef;
-    pub fn LLVMConstXor(LHSConstant: ValueRef, RHSConstant: ValueRef)
-                        -> ValueRef;
-    pub fn LLVMConstShl(LHSConstant: ValueRef, RHSConstant: ValueRef)
-                        -> ValueRef;
-    pub fn LLVMConstLShr(LHSConstant: ValueRef, RHSConstant: ValueRef)
-                         -> ValueRef;
-    pub fn LLVMConstAShr(LHSConstant: ValueRef, RHSConstant: ValueRef)
-                         -> ValueRef;
-    pub fn LLVMConstGEP(ConstantVal: ValueRef,
-                        ConstantIndices: *const ValueRef,
-                        NumIndices: c_uint)
-                        -> ValueRef;
-    pub fn LLVMConstInBoundsGEP(ConstantVal: ValueRef,
-                                ConstantIndices: *const ValueRef,
-                                NumIndices: c_uint)
-                                -> ValueRef;
-    pub fn LLVMConstTrunc(ConstantVal: ValueRef, ToType: TypeRef)
-                          -> ValueRef;
-    pub fn LLVMConstSExt(ConstantVal: ValueRef, ToType: TypeRef)
-                         -> ValueRef;
-    pub fn LLVMConstZExt(ConstantVal: ValueRef, ToType: TypeRef)
-                         -> ValueRef;
-    pub fn LLVMConstFPTrunc(ConstantVal: ValueRef, ToType: TypeRef)
-                            -> ValueRef;
-    pub fn LLVMConstFPExt(ConstantVal: ValueRef, ToType: TypeRef)
-                          -> ValueRef;
-    pub fn LLVMConstUIToFP(ConstantVal: ValueRef, ToType: TypeRef)
-                           -> ValueRef;
-    pub fn LLVMConstSIToFP(ConstantVal: ValueRef, ToType: TypeRef)
-                           -> ValueRef;
-    pub fn LLVMConstFPToUI(ConstantVal: ValueRef, ToType: TypeRef)
-                           -> ValueRef;
-    pub fn LLVMConstFPToSI(ConstantVal: ValueRef, ToType: TypeRef)
-                           -> ValueRef;
-    pub fn LLVMConstPtrToInt(ConstantVal: ValueRef, ToType: TypeRef)
-                             -> ValueRef;
-    pub fn LLVMConstIntToPtr(ConstantVal: ValueRef, ToType: TypeRef)
-                             -> ValueRef;
-    pub fn LLVMConstBitCast(ConstantVal: ValueRef, ToType: TypeRef)
-                            -> ValueRef;
-    pub fn LLVMConstZExtOrBitCast(ConstantVal: ValueRef, ToType: TypeRef)
-                                  -> ValueRef;
-    pub fn LLVMConstSExtOrBitCast(ConstantVal: ValueRef, ToType: TypeRef)
-                                  -> ValueRef;
-    pub fn LLVMConstTruncOrBitCast(ConstantVal: ValueRef, ToType: TypeRef)
-                                   -> ValueRef;
-    pub fn LLVMConstPointerCast(ConstantVal: ValueRef, ToType: TypeRef)
-                                -> ValueRef;
-    pub fn LLVMConstIntCast(ConstantVal: ValueRef,
-                            ToType: TypeRef,
-                            isSigned: Bool)
-                            -> ValueRef;
-    pub fn LLVMConstFPCast(ConstantVal: ValueRef, ToType: TypeRef)
-                           -> ValueRef;
-    pub fn LLVMConstSelect(ConstantCondition: ValueRef,
-                           ConstantIfTrue: ValueRef,
-                           ConstantIfFalse: ValueRef)
-                           -> ValueRef;
-    pub fn LLVMConstExtractElement(VectorConstant: ValueRef,
-                                   IndexConstant: ValueRef)
-                                   -> ValueRef;
-    pub fn LLVMConstInsertElement(VectorConstant: ValueRef,
-                                  ElementValueConstant: ValueRef,
-                                  IndexConstant: ValueRef)
-                                  -> ValueRef;
-    pub fn LLVMConstShuffleVector(VectorAConstant: ValueRef,
-                                  VectorBConstant: ValueRef,
-                                  MaskConstant: ValueRef)
-                                  -> ValueRef;
-    pub fn LLVMConstExtractValue(AggConstant: ValueRef,
-                                 IdxList: *const c_uint,
-                                 NumIdx: c_uint)
-                                 -> ValueRef;
-    pub fn LLVMConstInsertValue(AggConstant: ValueRef,
-                                ElementValueConstant: ValueRef,
-                                IdxList: *const c_uint,
-                                NumIdx: c_uint)
-                                -> ValueRef;
-    pub fn LLVMConstInlineAsm(Ty: TypeRef,
-                              AsmString: *const c_char,
-                              Constraints: *const c_char,
-                              HasSideEffects: Bool,
-                              IsAlignStack: Bool)
-                              -> ValueRef;
-    pub fn LLVMBlockAddress(F: ValueRef, BB: BasicBlockRef) -> ValueRef;
-
-
-
-    /* Operations on global variables, functions, and aliases (globals) */
-    pub fn LLVMGetGlobalParent(Global: ValueRef) -> ModuleRef;
-    pub fn LLVMIsDeclaration(Global: ValueRef) -> Bool;
-    pub fn LLVMGetLinkage(Global: ValueRef) -> c_uint;
-    pub fn LLVMSetLinkage(Global: ValueRef, Link: c_uint);
-    pub fn LLVMGetSection(Global: ValueRef) -> *const c_char;
-    pub fn LLVMSetSection(Global: ValueRef, Section: *const c_char);
-    pub fn LLVMGetVisibility(Global: ValueRef) -> c_uint;
-    pub fn LLVMSetVisibility(Global: ValueRef, Viz: c_uint);
-    pub fn LLVMGetAlignment(Global: ValueRef) -> c_uint;
-    pub fn LLVMSetAlignment(Global: ValueRef, Bytes: c_uint);
-
-
-    /* Operations on global variables */
-    pub fn LLVMIsAGlobalVariable(GlobalVar: ValueRef) -> ValueRef;
-    pub fn LLVMAddGlobal(M: ModuleRef, Ty: TypeRef, Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMAddGlobalInAddressSpace(M: ModuleRef,
-                                       Ty: TypeRef,
-                                       Name: *const c_char,
-                                       AddressSpace: c_uint)
-                                       -> ValueRef;
-    pub fn LLVMGetNamedGlobal(M: ModuleRef, Name: *const c_char) -> ValueRef;
-    pub fn LLVMGetOrInsertGlobal(M: ModuleRef, Name: *const c_char, T: TypeRef) -> ValueRef;
-    pub fn LLVMGetFirstGlobal(M: ModuleRef) -> ValueRef;
-    pub fn LLVMGetLastGlobal(M: ModuleRef) -> ValueRef;
-    pub fn LLVMGetNextGlobal(GlobalVar: ValueRef) -> ValueRef;
-    pub fn LLVMGetPreviousGlobal(GlobalVar: ValueRef) -> ValueRef;
-    pub fn LLVMDeleteGlobal(GlobalVar: ValueRef);
-    pub fn LLVMGetInitializer(GlobalVar: ValueRef) -> ValueRef;
-    pub fn LLVMSetInitializer(GlobalVar: ValueRef,
-                              ConstantVal: ValueRef);
-    pub fn LLVMIsThreadLocal(GlobalVar: ValueRef) -> Bool;
-    pub fn LLVMSetThreadLocal(GlobalVar: ValueRef, IsThreadLocal: Bool);
-    pub fn LLVMIsGlobalConstant(GlobalVar: ValueRef) -> Bool;
-    pub fn LLVMSetGlobalConstant(GlobalVar: ValueRef, IsConstant: Bool);
-    pub fn LLVMGetNamedValue(M: ModuleRef, Name: *const c_char) -> ValueRef;
-
-    /* Operations on aliases */
-    pub fn LLVMAddAlias(M: ModuleRef,
-                        Ty: TypeRef,
-                        Aliasee: ValueRef,
-                        Name: *const c_char)
-                        -> ValueRef;
-
-    /* Operations on functions */
-    pub fn LLVMAddFunction(M: ModuleRef,
-                           Name: *const c_char,
-                           FunctionTy: TypeRef)
-                           -> ValueRef;
-    pub fn LLVMGetNamedFunction(M: ModuleRef, Name: *const c_char) -> ValueRef;
-    pub fn LLVMGetFirstFunction(M: ModuleRef) -> ValueRef;
-    pub fn LLVMGetLastFunction(M: ModuleRef) -> ValueRef;
-    pub fn LLVMGetNextFunction(Fn: ValueRef) -> ValueRef;
-    pub fn LLVMGetPreviousFunction(Fn: ValueRef) -> ValueRef;
-    pub fn LLVMDeleteFunction(Fn: ValueRef);
-    pub fn LLVMGetOrInsertFunction(M: ModuleRef,
-                                   Name: *const c_char,
-                                   FunctionTy: TypeRef)
-                                   -> ValueRef;
-    pub fn LLVMGetIntrinsicID(Fn: ValueRef) -> c_uint;
-    pub fn LLVMGetFunctionCallConv(Fn: ValueRef) -> c_uint;
-    pub fn LLVMSetFunctionCallConv(Fn: ValueRef, CC: c_uint);
-    pub fn LLVMGetGC(Fn: ValueRef) -> *const c_char;
-    pub fn LLVMSetGC(Fn: ValueRef, Name: *const c_char);
-    pub fn LLVMAddDereferenceableAttr(Fn: ValueRef, index: c_uint, bytes: uint64_t);
-    pub fn LLVMAddFunctionAttribute(Fn: ValueRef, index: c_uint, PA: uint64_t);
-    pub fn LLVMAddFunctionAttrString(Fn: ValueRef, index: c_uint, Name: *const c_char);
-    pub fn LLVMAddFunctionAttrStringValue(Fn: ValueRef, index: c_uint,
-                                          Name: *const c_char,
-                                          Value: *const c_char);
-    pub fn LLVMRemoveFunctionAttributes(Fn: ValueRef, index: c_uint, attr: uint64_t);
-    pub fn LLVMRemoveFunctionAttrString(Fn: ValueRef, index: c_uint, Name: *const c_char);
-    pub fn LLVMGetFunctionAttr(Fn: ValueRef) -> c_uint;
-    pub fn LLVMRemoveFunctionAttr(Fn: ValueRef, val: c_uint);
-
-    /* Operations on parameters */
-    pub fn LLVMCountParams(Fn: ValueRef) -> c_uint;
-    pub fn LLVMGetParams(Fn: ValueRef, Params: *const ValueRef);
-    pub fn LLVMGetParam(Fn: ValueRef, Index: c_uint) -> ValueRef;
-    pub fn LLVMGetParamParent(Inst: ValueRef) -> ValueRef;
-    pub fn LLVMGetFirstParam(Fn: ValueRef) -> ValueRef;
-    pub fn LLVMGetLastParam(Fn: ValueRef) -> ValueRef;
-    pub fn LLVMGetNextParam(Arg: ValueRef) -> ValueRef;
-    pub fn LLVMGetPreviousParam(Arg: ValueRef) -> ValueRef;
-    pub fn LLVMAddAttribute(Arg: ValueRef, PA: c_uint);
-    pub fn LLVMRemoveAttribute(Arg: ValueRef, PA: c_uint);
-    pub fn LLVMGetAttribute(Arg: ValueRef) -> c_uint;
-    pub fn LLVMSetParamAlignment(Arg: ValueRef, align: c_uint);
-
-    /* Operations on basic blocks */
-    pub fn LLVMBasicBlockAsValue(BB: BasicBlockRef) -> ValueRef;
-    pub fn LLVMValueIsBasicBlock(Val: ValueRef) -> Bool;
-    pub fn LLVMValueAsBasicBlock(Val: ValueRef) -> BasicBlockRef;
-    pub fn LLVMGetBasicBlockParent(BB: BasicBlockRef) -> ValueRef;
-    pub fn LLVMCountBasicBlocks(Fn: ValueRef) -> c_uint;
-    pub fn LLVMGetBasicBlocks(Fn: ValueRef, BasicBlocks: *const ValueRef);
-    pub fn LLVMGetFirstBasicBlock(Fn: ValueRef) -> BasicBlockRef;
-    pub fn LLVMGetLastBasicBlock(Fn: ValueRef) -> BasicBlockRef;
-    pub fn LLVMGetNextBasicBlock(BB: BasicBlockRef) -> BasicBlockRef;
-    pub fn LLVMGetPreviousBasicBlock(BB: BasicBlockRef) -> BasicBlockRef;
-    pub fn LLVMGetEntryBasicBlock(Fn: ValueRef) -> BasicBlockRef;
-
-    pub fn LLVMAppendBasicBlockInContext(C: ContextRef,
-                                         Fn: ValueRef,
-                                         Name: *const c_char)
-                                         -> BasicBlockRef;
-    pub fn LLVMInsertBasicBlockInContext(C: ContextRef,
-                                         BB: BasicBlockRef,
-                                         Name: *const c_char)
-                                         -> BasicBlockRef;
-    pub fn LLVMDeleteBasicBlock(BB: BasicBlockRef);
-
-    pub fn LLVMMoveBasicBlockAfter(BB: BasicBlockRef,
-                                   MoveAfter: BasicBlockRef);
-
-    pub fn LLVMMoveBasicBlockBefore(BB: BasicBlockRef,
-                                    MoveBefore: BasicBlockRef);
-
-    /* Operations on instructions */
-    pub fn LLVMGetInstructionParent(Inst: ValueRef) -> BasicBlockRef;
-    pub fn LLVMGetFirstInstruction(BB: BasicBlockRef) -> ValueRef;
-    pub fn LLVMGetLastInstruction(BB: BasicBlockRef) -> ValueRef;
-    pub fn LLVMGetNextInstruction(Inst: ValueRef) -> ValueRef;
-    pub fn LLVMGetPreviousInstruction(Inst: ValueRef) -> ValueRef;
-    pub fn LLVMInstructionEraseFromParent(Inst: ValueRef);
-
-    /* Operations on call sites */
-    pub fn LLVMSetInstructionCallConv(Instr: ValueRef, CC: c_uint);
-    pub fn LLVMGetInstructionCallConv(Instr: ValueRef) -> c_uint;
-    pub fn LLVMAddInstrAttribute(Instr: ValueRef,
-                                 index: c_uint,
-                                 IA: c_uint);
-    pub fn LLVMRemoveInstrAttribute(Instr: ValueRef,
-                                    index: c_uint,
-                                    IA: c_uint);
-    pub fn LLVMSetInstrParamAlignment(Instr: ValueRef,
-                                      index: c_uint,
-                                      align: c_uint);
-    pub fn LLVMAddCallSiteAttribute(Instr: ValueRef,
-                                    index: c_uint,
-                                    Val: uint64_t);
-    pub fn LLVMAddDereferenceableCallSiteAttr(Instr: ValueRef,
-                                              index: c_uint,
-                                              bytes: uint64_t);
-
-    /* Operations on call instructions (only) */
-    pub fn LLVMIsTailCall(CallInst: ValueRef) -> Bool;
-    pub fn LLVMSetTailCall(CallInst: ValueRef, IsTailCall: Bool);
-
-    /* Operations on load/store instructions (only) */
-    pub fn LLVMGetVolatile(MemoryAccessInst: ValueRef) -> Bool;
-    pub fn LLVMSetVolatile(MemoryAccessInst: ValueRef, volatile: Bool);
-
-    /* Operations on phi nodes */
-    pub fn LLVMAddIncoming(PhiNode: ValueRef,
-                           IncomingValues: *const ValueRef,
-                           IncomingBlocks: *const BasicBlockRef,
-                           Count: c_uint);
-    pub fn LLVMCountIncoming(PhiNode: ValueRef) -> c_uint;
-    pub fn LLVMGetIncomingValue(PhiNode: ValueRef, Index: c_uint)
-                                -> ValueRef;
-    pub fn LLVMGetIncomingBlock(PhiNode: ValueRef, Index: c_uint)
-                                -> BasicBlockRef;
-
-    /* Instruction builders */
-    pub fn LLVMCreateBuilderInContext(C: ContextRef) -> BuilderRef;
-    pub fn LLVMPositionBuilder(Builder: BuilderRef,
-                               Block: BasicBlockRef,
-                               Instr: ValueRef);
-    pub fn LLVMPositionBuilderBefore(Builder: BuilderRef,
-                                     Instr: ValueRef);
-    pub fn LLVMPositionBuilderAtEnd(Builder: BuilderRef,
-                                    Block: BasicBlockRef);
-    pub fn LLVMGetInsertBlock(Builder: BuilderRef) -> BasicBlockRef;
-    pub fn LLVMClearInsertionPosition(Builder: BuilderRef);
-    pub fn LLVMInsertIntoBuilder(Builder: BuilderRef, Instr: ValueRef);
-    pub fn LLVMInsertIntoBuilderWithName(Builder: BuilderRef,
-                                         Instr: ValueRef,
-                                         Name: *const c_char);
-    pub fn LLVMDisposeBuilder(Builder: BuilderRef);
-
-    /* Execution engine */
-    pub fn LLVMBuildExecutionEngine(Mod: ModuleRef) -> ExecutionEngineRef;
-    pub fn LLVMDisposeExecutionEngine(EE: ExecutionEngineRef);
-    pub fn LLVMExecutionEngineFinalizeObject(EE: ExecutionEngineRef);
-    pub fn LLVMRustLoadDynamicLibrary(path: *const c_char) -> Bool;
-    pub fn LLVMExecutionEngineAddModule(EE: ExecutionEngineRef, M: ModuleRef);
-    pub fn LLVMExecutionEngineRemoveModule(EE: ExecutionEngineRef, M: ModuleRef)
-                                           -> Bool;
-
-    /* Metadata */
-    pub fn LLVMSetCurrentDebugLocation(Builder: BuilderRef, L: ValueRef);
-    pub fn LLVMGetCurrentDebugLocation(Builder: BuilderRef) -> ValueRef;
-    pub fn LLVMSetInstDebugLocation(Builder: BuilderRef, Inst: ValueRef);
-
-    /* Terminators */
-    pub fn LLVMBuildRetVoid(B: BuilderRef) -> ValueRef;
-    pub fn LLVMBuildRet(B: BuilderRef, V: ValueRef) -> ValueRef;
-    pub fn LLVMBuildAggregateRet(B: BuilderRef,
-                                 RetVals: *const ValueRef,
-                                 N: c_uint)
-                                 -> ValueRef;
-    pub fn LLVMBuildBr(B: BuilderRef, Dest: BasicBlockRef) -> ValueRef;
-    pub fn LLVMBuildCondBr(B: BuilderRef,
-                           If: ValueRef,
-                           Then: BasicBlockRef,
-                           Else: BasicBlockRef)
-                           -> ValueRef;
-    pub fn LLVMBuildSwitch(B: BuilderRef,
-                           V: ValueRef,
-                           Else: BasicBlockRef,
-                           NumCases: c_uint)
-                           -> ValueRef;
-    pub fn LLVMBuildIndirectBr(B: BuilderRef,
-                               Addr: ValueRef,
-                               NumDests: c_uint)
-                               -> ValueRef;
-    pub fn LLVMRustBuildInvoke(B: BuilderRef,
-                               Fn: ValueRef,
-                               Args: *const ValueRef,
-                               NumArgs: c_uint,
-                               Then: BasicBlockRef,
-                               Catch: BasicBlockRef,
-                               Bundle: OperandBundleDefRef,
-                               Name: *const c_char)
-                               -> ValueRef;
-    pub fn LLVMRustBuildLandingPad(B: BuilderRef,
-                                   Ty: TypeRef,
-                                   PersFn: ValueRef,
-                                   NumClauses: c_uint,
-                                   Name: *const c_char,
-                                   F: ValueRef)
-                                   -> ValueRef;
-    pub fn LLVMBuildResume(B: BuilderRef, Exn: ValueRef) -> ValueRef;
-    pub fn LLVMBuildUnreachable(B: BuilderRef) -> ValueRef;
-
-    pub fn LLVMRustBuildCleanupPad(B: BuilderRef,
-                                   ParentPad: ValueRef,
-                                   ArgCnt: c_uint,
-                                   Args: *const ValueRef,
-                                   Name: *const c_char) -> ValueRef;
-    pub fn LLVMRustBuildCleanupRet(B: BuilderRef,
-                                   CleanupPad: ValueRef,
-                                   UnwindBB: BasicBlockRef) -> ValueRef;
-    pub fn LLVMRustBuildCatchPad(B: BuilderRef,
-                                 ParentPad: ValueRef,
-                                 ArgCnt: c_uint,
-                                 Args: *const ValueRef,
-                                 Name: *const c_char) -> ValueRef;
-    pub fn LLVMRustBuildCatchRet(B: BuilderRef,
-                                 Pad: ValueRef,
-                                 BB: BasicBlockRef) -> ValueRef;
-    pub fn LLVMRustBuildCatchSwitch(Builder: BuilderRef,
-                                    ParentPad: ValueRef,
-                                    BB: BasicBlockRef,
-                                    NumHandlers: c_uint,
-                                    Name: *const c_char) -> ValueRef;
-    pub fn LLVMRustAddHandler(CatchSwitch: ValueRef,
-                              Handler: BasicBlockRef);
-    pub fn LLVMRustSetPersonalityFn(B: BuilderRef, Pers: ValueRef);
-
-    /* Add a case to the switch instruction */
-    pub fn LLVMAddCase(Switch: ValueRef,
-                       OnVal: ValueRef,
-                       Dest: BasicBlockRef);
-
-    /* Add a destination to the indirectbr instruction */
-    pub fn LLVMAddDestination(IndirectBr: ValueRef, Dest: BasicBlockRef);
-
-    /* Add a clause to the landing pad instruction */
-    pub fn LLVMAddClause(LandingPad: ValueRef, ClauseVal: ValueRef);
-
-    /* Set the cleanup on a landing pad instruction */
-    pub fn LLVMSetCleanup(LandingPad: ValueRef, Val: Bool);
-
-    /* Arithmetic */
-    pub fn LLVMBuildAdd(B: BuilderRef,
-                        LHS: ValueRef,
-                        RHS: ValueRef,
-                        Name: *const c_char)
-                        -> ValueRef;
-    pub fn LLVMBuildNSWAdd(B: BuilderRef,
-                           LHS: ValueRef,
-                           RHS: ValueRef,
-                           Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildNUWAdd(B: BuilderRef,
-                           LHS: ValueRef,
-                           RHS: ValueRef,
-                           Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildFAdd(B: BuilderRef,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildSub(B: BuilderRef,
-                        LHS: ValueRef,
-                        RHS: ValueRef,
-                        Name: *const c_char)
-                        -> ValueRef;
-    pub fn LLVMBuildNSWSub(B: BuilderRef,
-                           LHS: ValueRef,
-                           RHS: ValueRef,
-                           Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildNUWSub(B: BuilderRef,
-                           LHS: ValueRef,
-                           RHS: ValueRef,
-                           Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildFSub(B: BuilderRef,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildMul(B: BuilderRef,
-                        LHS: ValueRef,
-                        RHS: ValueRef,
-                        Name: *const c_char)
-                        -> ValueRef;
-    pub fn LLVMBuildNSWMul(B: BuilderRef,
-                           LHS: ValueRef,
-                           RHS: ValueRef,
-                           Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildNUWMul(B: BuilderRef,
-                           LHS: ValueRef,
-                           RHS: ValueRef,
-                           Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildFMul(B: BuilderRef,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildUDiv(B: BuilderRef,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildSDiv(B: BuilderRef,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildExactSDiv(B: BuilderRef,
-                              LHS: ValueRef,
-                              RHS: ValueRef,
-                              Name: *const c_char)
-                              -> ValueRef;
-    pub fn LLVMBuildFDiv(B: BuilderRef,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildURem(B: BuilderRef,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildSRem(B: BuilderRef,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildFRem(B: BuilderRef,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildShl(B: BuilderRef,
-                        LHS: ValueRef,
-                        RHS: ValueRef,
-                        Name: *const c_char)
-                        -> ValueRef;
-    pub fn LLVMBuildLShr(B: BuilderRef,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildAShr(B: BuilderRef,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildAnd(B: BuilderRef,
-                        LHS: ValueRef,
-                        RHS: ValueRef,
-                        Name: *const c_char)
-                        -> ValueRef;
-    pub fn LLVMBuildOr(B: BuilderRef,
-                       LHS: ValueRef,
-                       RHS: ValueRef,
-                       Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildXor(B: BuilderRef,
-                        LHS: ValueRef,
-                        RHS: ValueRef,
-                        Name: *const c_char)
-                        -> ValueRef;
-    pub fn LLVMBuildBinOp(B: BuilderRef,
-                          Op: Opcode,
-                          LHS: ValueRef,
-                          RHS: ValueRef,
-                          Name: *const c_char)
-                          -> ValueRef;
-    pub fn LLVMBuildNeg(B: BuilderRef, V: ValueRef, Name: *const c_char)
-                        -> ValueRef;
-    pub fn LLVMBuildNSWNeg(B: BuilderRef, V: ValueRef, Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildNUWNeg(B: BuilderRef, V: ValueRef, Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildFNeg(B: BuilderRef, V: ValueRef, Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildNot(B: BuilderRef, V: ValueRef, Name: *const c_char)
-                        -> ValueRef;
-    pub fn LLVMRustSetHasUnsafeAlgebra(Instr: ValueRef);
-
-    /* Memory */
-    pub fn LLVMBuildAlloca(B: BuilderRef, Ty: TypeRef, Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildFree(B: BuilderRef, PointerVal: ValueRef) -> ValueRef;
-    pub fn LLVMBuildLoad(B: BuilderRef,
-                         PointerVal: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-
-    pub fn LLVMBuildStore(B: BuilderRef, Val: ValueRef, Ptr: ValueRef)
-                          -> ValueRef;
-
-    pub fn LLVMBuildGEP(B: BuilderRef,
-                        Pointer: ValueRef,
-                        Indices: *const ValueRef,
-                        NumIndices: c_uint,
-                        Name: *const c_char)
-                        -> ValueRef;
-    pub fn LLVMBuildInBoundsGEP(B: BuilderRef,
-                                Pointer: ValueRef,
-                                Indices: *const ValueRef,
-                                NumIndices: c_uint,
-                                Name: *const c_char)
-                                -> ValueRef;
-    pub fn LLVMBuildStructGEP(B: BuilderRef,
-                              Pointer: ValueRef,
-                              Idx: c_uint,
-                              Name: *const c_char)
-                              -> ValueRef;
-    pub fn LLVMBuildGlobalString(B: BuilderRef,
-                                 Str: *const c_char,
-                                 Name: *const c_char)
-                                 -> ValueRef;
-    pub fn LLVMBuildGlobalStringPtr(B: BuilderRef,
-                                    Str: *const c_char,
-                                    Name: *const c_char)
-                                    -> ValueRef;
-
-    /* Casts */
-    pub fn LLVMBuildTrunc(B: BuilderRef,
-                          Val: ValueRef,
-                          DestTy: TypeRef,
-                          Name: *const c_char)
-                          -> ValueRef;
-    pub fn LLVMBuildZExt(B: BuilderRef,
-                         Val: ValueRef,
-                         DestTy: TypeRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildSExt(B: BuilderRef,
-                         Val: ValueRef,
-                         DestTy: TypeRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildFPToUI(B: BuilderRef,
-                           Val: ValueRef,
-                           DestTy: TypeRef,
-                           Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildFPToSI(B: BuilderRef,
-                           Val: ValueRef,
-                           DestTy: TypeRef,
-                           Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildUIToFP(B: BuilderRef,
-                           Val: ValueRef,
-                           DestTy: TypeRef,
-                           Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildSIToFP(B: BuilderRef,
-                           Val: ValueRef,
-                           DestTy: TypeRef,
-                           Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildFPTrunc(B: BuilderRef,
-                            Val: ValueRef,
-                            DestTy: TypeRef,
-                            Name: *const c_char)
-                            -> ValueRef;
-    pub fn LLVMBuildFPExt(B: BuilderRef,
-                          Val: ValueRef,
-                          DestTy: TypeRef,
-                          Name: *const c_char)
-                          -> ValueRef;
-    pub fn LLVMBuildPtrToInt(B: BuilderRef,
-                             Val: ValueRef,
-                             DestTy: TypeRef,
-                             Name: *const c_char)
-                             -> ValueRef;
-    pub fn LLVMBuildIntToPtr(B: BuilderRef,
-                             Val: ValueRef,
-                             DestTy: TypeRef,
-                             Name: *const c_char)
-                             -> ValueRef;
-    pub fn LLVMBuildBitCast(B: BuilderRef,
-                            Val: ValueRef,
-                            DestTy: TypeRef,
-                            Name: *const c_char)
-                            -> ValueRef;
-    pub fn LLVMBuildZExtOrBitCast(B: BuilderRef,
-                                  Val: ValueRef,
-                                  DestTy: TypeRef,
-                                  Name: *const c_char)
-                                  -> ValueRef;
-    pub fn LLVMBuildSExtOrBitCast(B: BuilderRef,
-                                  Val: ValueRef,
-                                  DestTy: TypeRef,
-                                  Name: *const c_char)
-                                  -> ValueRef;
-    pub fn LLVMBuildTruncOrBitCast(B: BuilderRef,
-                                   Val: ValueRef,
-                                   DestTy: TypeRef,
-                                   Name: *const c_char)
-                                   -> ValueRef;
-    pub fn LLVMBuildCast(B: BuilderRef,
-                         Op: Opcode,
-                         Val: ValueRef,
-                         DestTy: TypeRef,
-                         Name: *const c_char) -> ValueRef;
-    pub fn LLVMBuildPointerCast(B: BuilderRef,
-                                Val: ValueRef,
-                                DestTy: TypeRef,
-                                Name: *const c_char)
-                                -> ValueRef;
-    pub fn LLVMBuildIntCast(B: BuilderRef,
-                            Val: ValueRef,
-                            DestTy: TypeRef,
-                            Name: *const c_char)
-                            -> ValueRef;
-    pub fn LLVMBuildFPCast(B: BuilderRef,
-                           Val: ValueRef,
-                           DestTy: TypeRef,
-                           Name: *const c_char)
-                           -> ValueRef;
-
-    /* Comparisons */
-    pub fn LLVMBuildICmp(B: BuilderRef,
-                         Op: c_uint,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildFCmp(B: BuilderRef,
-                         Op: c_uint,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-
-    /* Miscellaneous instructions */
-    pub fn LLVMBuildPhi(B: BuilderRef, Ty: TypeRef, Name: *const c_char)
-                        -> ValueRef;
-    pub fn LLVMRustBuildCall(B: BuilderRef,
-                             Fn: ValueRef,
-                             Args: *const ValueRef,
-                             NumArgs: c_uint,
-                             Bundle: OperandBundleDefRef,
-                             Name: *const c_char)
-                             -> ValueRef;
-    pub fn LLVMBuildSelect(B: BuilderRef,
-                           If: ValueRef,
-                           Then: ValueRef,
-                           Else: ValueRef,
-                           Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildVAArg(B: BuilderRef,
-                          list: ValueRef,
-                          Ty: TypeRef,
-                          Name: *const c_char)
-                          -> ValueRef;
-    pub fn LLVMBuildExtractElement(B: BuilderRef,
-                                   VecVal: ValueRef,
-                                   Index: ValueRef,
-                                   Name: *const c_char)
-                                   -> ValueRef;
-    pub fn LLVMBuildInsertElement(B: BuilderRef,
-                                  VecVal: ValueRef,
-                                  EltVal: ValueRef,
-                                  Index: ValueRef,
-                                  Name: *const c_char)
-                                  -> ValueRef;
-    pub fn LLVMBuildShuffleVector(B: BuilderRef,
-                                  V1: ValueRef,
-                                  V2: ValueRef,
-                                  Mask: ValueRef,
-                                  Name: *const c_char)
-                                  -> ValueRef;
-    pub fn LLVMBuildExtractValue(B: BuilderRef,
-                                 AggVal: ValueRef,
-                                 Index: c_uint,
-                                 Name: *const c_char)
-                                 -> ValueRef;
-    pub fn LLVMBuildInsertValue(B: BuilderRef,
-                                AggVal: ValueRef,
-                                EltVal: ValueRef,
-                                Index: c_uint,
-                                Name: *const c_char)
-                                -> ValueRef;
-
-    pub fn LLVMBuildIsNull(B: BuilderRef, Val: ValueRef, Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildIsNotNull(B: BuilderRef, Val: ValueRef, Name: *const c_char)
-                              -> ValueRef;
-    pub fn LLVMBuildPtrDiff(B: BuilderRef,
-                            LHS: ValueRef,
-                            RHS: ValueRef,
-                            Name: *const c_char)
-                            -> ValueRef;
-
-    /* Atomic Operations */
-    pub fn LLVMBuildAtomicLoad(B: BuilderRef,
-                               PointerVal: ValueRef,
-                               Name: *const c_char,
-                               Order: AtomicOrdering,
-                               Alignment: c_uint)
-                               -> ValueRef;
-
-    pub fn LLVMBuildAtomicStore(B: BuilderRef,
-                                Val: ValueRef,
-                                Ptr: ValueRef,
-                                Order: AtomicOrdering,
-                                Alignment: c_uint)
-                                -> ValueRef;
-
-    pub fn LLVMBuildAtomicCmpXchg(B: BuilderRef,
-                                  LHS: ValueRef,
-                                  CMP: ValueRef,
-                                  RHS: ValueRef,
-                                  Order: AtomicOrdering,
-                                  FailureOrder: AtomicOrdering,
-                                  Weak: Bool)
-                                  -> ValueRef;
-    pub fn LLVMBuildAtomicRMW(B: BuilderRef,
-                              Op: AtomicBinOp,
-                              LHS: ValueRef,
-                              RHS: ValueRef,
-                              Order: AtomicOrdering,
-                              SingleThreaded: Bool)
-                              -> ValueRef;
-
-    pub fn LLVMBuildAtomicFence(B: BuilderRef,
-                                Order: AtomicOrdering,
-                                Scope: SynchronizationScope);
-
-
-    /* Selected entries from the downcasts. */
-    pub fn LLVMIsATerminatorInst(Inst: ValueRef) -> ValueRef;
-    pub fn LLVMIsAStoreInst(Inst: ValueRef) -> ValueRef;
-
-    /// Writes a module to the specified path. Returns 0 on success.
-    pub fn LLVMWriteBitcodeToFile(M: ModuleRef, Path: *const c_char) -> c_int;
-
-    /// Creates target data from a target layout string.
-    pub fn LLVMCreateTargetData(StringRep: *const c_char) -> TargetDataRef;
-    /// Adds the target data to the given pass manager. The pass manager
-    /// references the target data only weakly.
-    pub fn LLVMAddTargetData(TD: TargetDataRef, PM: PassManagerRef);
-    /// Number of bytes clobbered when doing a Store to *T.
-    pub fn LLVMStoreSizeOfType(TD: TargetDataRef, Ty: TypeRef)
-                               -> c_ulonglong;
-
-    /// Number of bytes clobbered when doing a Store to *T.
-    pub fn LLVMSizeOfTypeInBits(TD: TargetDataRef, Ty: TypeRef)
-                                -> c_ulonglong;
-
-    /// Distance between successive elements in an array of T. Includes ABI padding.
-    pub fn LLVMABISizeOfType(TD: TargetDataRef, Ty: TypeRef) -> c_ulonglong;
-
-    /// Returns the preferred alignment of a type.
-    pub fn LLVMPreferredAlignmentOfType(TD: TargetDataRef, Ty: TypeRef)
-                                        -> c_uint;
-    /// Returns the minimum alignment of a type.
-    pub fn LLVMABIAlignmentOfType(TD: TargetDataRef, Ty: TypeRef)
-                                  -> c_uint;
-
-    /// Computes the byte offset of the indexed struct element for a
-    /// target.
-    pub fn LLVMOffsetOfElement(TD: TargetDataRef,
-                               StructTy: TypeRef,
-                               Element: c_uint)
-                               -> c_ulonglong;
-
-    /// Returns the minimum alignment of a type when part of a call frame.
-    pub fn LLVMCallFrameAlignmentOfType(TD: TargetDataRef, Ty: TypeRef)
-                                        -> c_uint;
-
-    /// Disposes target data.
-    pub fn LLVMDisposeTargetData(TD: TargetDataRef);
-
-    /// Creates a pass manager.
-    pub fn LLVMCreatePassManager() -> PassManagerRef;
-
-    /// Creates a function-by-function pass manager
-    pub fn LLVMCreateFunctionPassManagerForModule(M: ModuleRef)
-                                                  -> PassManagerRef;
-
-    /// Disposes a pass manager.
-    pub fn LLVMDisposePassManager(PM: PassManagerRef);
-
-    /// Runs a pass manager on a module.
-    pub fn LLVMRunPassManager(PM: PassManagerRef, M: ModuleRef) -> Bool;
-
-    /// Runs the function passes on the provided function.
-    pub fn LLVMRunFunctionPassManager(FPM: PassManagerRef, F: ValueRef)
-                                      -> Bool;
-
-    /// Initializes all the function passes scheduled in the manager
-    pub fn LLVMInitializeFunctionPassManager(FPM: PassManagerRef) -> Bool;
-
-    /// Finalizes all the function passes scheduled in the manager
-    pub fn LLVMFinalizeFunctionPassManager(FPM: PassManagerRef) -> Bool;
-
-    pub fn LLVMInitializePasses();
-
-    /// Adds a verification pass.
-    pub fn LLVMAddVerifierPass(PM: PassManagerRef);
-
-    pub fn LLVMAddGlobalOptimizerPass(PM: PassManagerRef);
-    pub fn LLVMAddIPSCCPPass(PM: PassManagerRef);
-    pub fn LLVMAddDeadArgEliminationPass(PM: PassManagerRef);
-    pub fn LLVMAddInstructionCombiningPass(PM: PassManagerRef);
-    pub fn LLVMAddCFGSimplificationPass(PM: PassManagerRef);
-    pub fn LLVMAddFunctionInliningPass(PM: PassManagerRef);
-    pub fn LLVMAddFunctionAttrsPass(PM: PassManagerRef);
-    pub fn LLVMAddScalarReplAggregatesPass(PM: PassManagerRef);
-    pub fn LLVMAddScalarReplAggregatesPassSSA(PM: PassManagerRef);
-    pub fn LLVMAddJumpThreadingPass(PM: PassManagerRef);
-    pub fn LLVMAddConstantPropagationPass(PM: PassManagerRef);
-    pub fn LLVMAddReassociatePass(PM: PassManagerRef);
-    pub fn LLVMAddLoopRotatePass(PM: PassManagerRef);
-    pub fn LLVMAddLICMPass(PM: PassManagerRef);
-    pub fn LLVMAddLoopUnswitchPass(PM: PassManagerRef);
-    pub fn LLVMAddLoopDeletionPass(PM: PassManagerRef);
-    pub fn LLVMAddLoopUnrollPass(PM: PassManagerRef);
-    pub fn LLVMAddGVNPass(PM: PassManagerRef);
-    pub fn LLVMAddMemCpyOptPass(PM: PassManagerRef);
-    pub fn LLVMAddSCCPPass(PM: PassManagerRef);
-    pub fn LLVMAddDeadStoreEliminationPass(PM: PassManagerRef);
-    pub fn LLVMAddStripDeadPrototypesPass(PM: PassManagerRef);
-    pub fn LLVMAddConstantMergePass(PM: PassManagerRef);
-    pub fn LLVMAddArgumentPromotionPass(PM: PassManagerRef);
-    pub fn LLVMAddTailCallEliminationPass(PM: PassManagerRef);
-    pub fn LLVMAddIndVarSimplifyPass(PM: PassManagerRef);
-    pub fn LLVMAddAggressiveDCEPass(PM: PassManagerRef);
-    pub fn LLVMAddGlobalDCEPass(PM: PassManagerRef);
-    pub fn LLVMAddCorrelatedValuePropagationPass(PM: PassManagerRef);
-    pub fn LLVMAddPruneEHPass(PM: PassManagerRef);
-    pub fn LLVMAddSimplifyLibCallsPass(PM: PassManagerRef);
-    pub fn LLVMAddLoopIdiomPass(PM: PassManagerRef);
-    pub fn LLVMAddEarlyCSEPass(PM: PassManagerRef);
-    pub fn LLVMAddTypeBasedAliasAnalysisPass(PM: PassManagerRef);
-    pub fn LLVMAddBasicAliasAnalysisPass(PM: PassManagerRef);
-
-    pub fn LLVMPassManagerBuilderCreate() -> PassManagerBuilderRef;
-    pub fn LLVMPassManagerBuilderDispose(PMB: PassManagerBuilderRef);
-    pub fn LLVMPassManagerBuilderSetOptLevel(PMB: PassManagerBuilderRef,
-                                             OptimizationLevel: c_uint);
-    pub fn LLVMPassManagerBuilderSetSizeLevel(PMB: PassManagerBuilderRef,
-                                              Value: Bool);
-    pub fn LLVMPassManagerBuilderSetDisableUnitAtATime(
-        PMB: PassManagerBuilderRef,
-        Value: Bool);
-    pub fn LLVMPassManagerBuilderSetDisableUnrollLoops(
-        PMB: PassManagerBuilderRef,
-        Value: Bool);
-    pub fn LLVMPassManagerBuilderSetDisableSimplifyLibCalls(
-        PMB: PassManagerBuilderRef,
-        Value: Bool);
-    pub fn LLVMPassManagerBuilderUseInlinerWithThreshold(
-        PMB: PassManagerBuilderRef,
-        threshold: c_uint);
-    pub fn LLVMPassManagerBuilderPopulateModulePassManager(
-        PMB: PassManagerBuilderRef,
-        PM: PassManagerRef);
-
-    pub fn LLVMPassManagerBuilderPopulateFunctionPassManager(
-        PMB: PassManagerBuilderRef,
-        PM: PassManagerRef);
-    pub fn LLVMPassManagerBuilderPopulateLTOPassManager(
-        PMB: PassManagerBuilderRef,
-        PM: PassManagerRef,
-        Internalize: Bool,
-        RunInliner: Bool);
-
-    /// Destroys a memory buffer.
-    pub fn LLVMDisposeMemoryBuffer(MemBuf: MemoryBufferRef);
-
-
-    /* Stuff that's in rustllvm/ because it's not upstream yet. */
-
-    /// Opens an object file.
-    pub fn LLVMCreateObjectFile(MemBuf: MemoryBufferRef) -> ObjectFileRef;
-    /// Closes an object file.
-    pub fn LLVMDisposeObjectFile(ObjFile: ObjectFileRef);
-
-    /// Enumerates the sections in an object file.
-    pub fn LLVMGetSections(ObjFile: ObjectFileRef) -> SectionIteratorRef;
-    /// Destroys a section iterator.
-    pub fn LLVMDisposeSectionIterator(SI: SectionIteratorRef);
-    /// Returns true if the section iterator is at the end of the section
-    /// list:
-    pub fn LLVMIsSectionIteratorAtEnd(ObjFile: ObjectFileRef,
-                                      SI: SectionIteratorRef)
-                                      -> Bool;
-    /// Moves the section iterator to point to the next section.
-    pub fn LLVMMoveToNextSection(SI: SectionIteratorRef);
-    /// Returns the current section size.
-    pub fn LLVMGetSectionSize(SI: SectionIteratorRef) -> c_ulonglong;
-    /// Returns the current section contents as a string buffer.
-    pub fn LLVMGetSectionContents(SI: SectionIteratorRef) -> *const c_char;
-
-    /// Reads the given file and returns it as a memory buffer. Use
-    /// LLVMDisposeMemoryBuffer() to get rid of it.
-    pub fn LLVMRustCreateMemoryBufferWithContentsOfFile(Path: *const c_char)
-                                                        -> MemoryBufferRef;
-    /// Borrows the contents of the memory buffer (doesn't copy it)
-    pub fn LLVMCreateMemoryBufferWithMemoryRange(InputData: *const c_char,
-                                                 InputDataLength: size_t,
-                                                 BufferName: *const c_char,
-                                                 RequiresNull: Bool)
-                                                 -> MemoryBufferRef;
-    pub fn LLVMCreateMemoryBufferWithMemoryRangeCopy(InputData: *const c_char,
-                                                     InputDataLength: size_t,
-                                                     BufferName: *const c_char)
-                                                     -> MemoryBufferRef;
-
-    pub fn LLVMIsMultithreaded() -> Bool;
-    pub fn LLVMStartMultithreaded() -> Bool;
-
-    /// Returns a string describing the last error caused by an LLVMRust* call.
-    pub fn LLVMRustGetLastError() -> *const c_char;
-
-    /// Print the pass timings since static dtors aren't picking them up.
-    pub fn LLVMRustPrintPassTimings();
-
-    pub fn LLVMStructCreateNamed(C: ContextRef, Name: *const c_char) -> TypeRef;
-
-    pub fn LLVMStructSetBody(StructTy: TypeRef,
-                             ElementTypes: *const TypeRef,
-                             ElementCount: c_uint,
-                             Packed: Bool);
-
-    pub fn LLVMConstNamedStruct(S: TypeRef,
-                                ConstantVals: *const ValueRef,
-                                Count: c_uint)
-                                -> ValueRef;
-
-    /// Enables LLVM debug output.
-    pub fn LLVMSetDebug(Enabled: c_int);
-
-    /// Prepares inline assembly.
-    pub fn LLVMInlineAsm(Ty: TypeRef,
-                         AsmString: *const c_char,
-                         Constraints: *const c_char,
-                         SideEffects: Bool,
-                         AlignStack: Bool,
-                         Dialect: c_uint)
-                         -> ValueRef;
-
-    pub fn LLVMRustDebugMetadataVersion() -> u32;
-    pub fn LLVMVersionMajor() -> u32;
-    pub fn LLVMVersionMinor() -> u32;
-
-    pub fn LLVMRustAddModuleFlag(M: ModuleRef,
-                                 name: *const c_char,
-                                 value: u32);
-
-    pub fn LLVMDIBuilderCreate(M: ModuleRef) -> DIBuilderRef;
-
-    pub fn LLVMDIBuilderDispose(Builder: DIBuilderRef);
-
-    pub fn LLVMDIBuilderFinalize(Builder: DIBuilderRef);
-
-    pub fn LLVMDIBuilderCreateCompileUnit(Builder: DIBuilderRef,
-                                          Lang: c_uint,
-                                          File: *const c_char,
-                                          Dir: *const c_char,
-                                          Producer: *const c_char,
-                                          isOptimized: bool,
-                                          Flags: *const c_char,
-                                          RuntimeVer: c_uint,
-                                          SplitName: *const c_char)
-                                          -> DIDescriptor;
-
-    pub fn LLVMDIBuilderCreateFile(Builder: DIBuilderRef,
-                                   Filename: *const c_char,
-                                   Directory: *const c_char)
-                                   -> DIFile;
-
-    pub fn LLVMDIBuilderCreateSubroutineType(Builder: DIBuilderRef,
-                                             File: DIFile,
-                                             ParameterTypes: DIArray)
-                                             -> DICompositeType;
-
-    pub fn LLVMDIBuilderCreateFunction(Builder: DIBuilderRef,
-                                       Scope: DIDescriptor,
-                                       Name: *const c_char,
-                                       LinkageName: *const c_char,
-                                       File: DIFile,
-                                       LineNo: c_uint,
-                                       Ty: DIType,
-                                       isLocalToUnit: bool,
-                                       isDefinition: bool,
-                                       ScopeLine: c_uint,
-                                       Flags: c_uint,
-                                       isOptimized: bool,
-                                       Fn: ValueRef,
-                                       TParam: DIArray,
-                                       Decl: DIDescriptor)
-                                       -> DISubprogram;
-
-    pub fn LLVMDIBuilderCreateBasicType(Builder: DIBuilderRef,
-                                        Name: *const c_char,
-                                        SizeInBits: c_ulonglong,
-                                        AlignInBits: c_ulonglong,
-                                        Encoding: c_uint)
-                                        -> DIBasicType;
-
-    pub fn LLVMDIBuilderCreatePointerType(Builder: DIBuilderRef,
-                                          PointeeTy: DIType,
-                                          SizeInBits: c_ulonglong,
-                                          AlignInBits: c_ulonglong,
-                                          Name: *const c_char)
-                                          -> DIDerivedType;
-
-    pub fn LLVMDIBuilderCreateStructType(Builder: DIBuilderRef,
-                                         Scope: DIDescriptor,
-                                         Name: *const c_char,
-                                         File: DIFile,
-                                         LineNumber: c_uint,
-                                         SizeInBits: c_ulonglong,
-                                         AlignInBits: c_ulonglong,
-                                         Flags: c_uint,
-                                         DerivedFrom: DIType,
-                                         Elements: DIArray,
-                                         RunTimeLang: c_uint,
-                                         VTableHolder: DIType,
-                                         UniqueId: *const c_char)
-                                         -> DICompositeType;
-
-    pub fn LLVMDIBuilderCreateMemberType(Builder: DIBuilderRef,
-                                         Scope: DIDescriptor,
-                                         Name: *const c_char,
-                                         File: DIFile,
-                                         LineNo: c_uint,
-                                         SizeInBits: c_ulonglong,
-                                         AlignInBits: c_ulonglong,
-                                         OffsetInBits: c_ulonglong,
-                                         Flags: c_uint,
-                                         Ty: DIType)
-                                         -> DIDerivedType;
-
-    pub fn LLVMDIBuilderCreateLexicalBlock(Builder: DIBuilderRef,
-                                           Scope: DIScope,
-                                           File: DIFile,
-                                           Line: c_uint,
-                                           Col: c_uint)
-                                           -> DILexicalBlock;
-
-    pub fn LLVMDIBuilderCreateStaticVariable(Builder: DIBuilderRef,
-                                             Context: DIScope,
-                                             Name: *const c_char,
-                                             LinkageName: *const c_char,
-                                             File: DIFile,
-                                             LineNo: c_uint,
-                                             Ty: DIType,
-                                             isLocalToUnit: bool,
-                                             Val: ValueRef,
-                                             Decl: DIDescriptor)
-                                             -> DIGlobalVariable;
-
-    pub fn LLVMDIBuilderCreateVariable(Builder: DIBuilderRef,
-                                            Tag: c_uint,
-                                            Scope: DIDescriptor,
-                                            Name: *const c_char,
-                                            File: DIFile,
-                                            LineNo: c_uint,
-                                            Ty: DIType,
-                                            AlwaysPreserve: bool,
-                                            Flags: c_uint,
-                                            AddrOps: *const i64,
-                                            AddrOpsCount: c_uint,
-                                            ArgNo: c_uint)
-                                            -> DIVariable;
-
-    pub fn LLVMDIBuilderCreateArrayType(Builder: DIBuilderRef,
-                                        Size: c_ulonglong,
-                                        AlignInBits: c_ulonglong,
-                                        Ty: DIType,
-                                        Subscripts: DIArray)
-                                        -> DIType;
-
-    pub fn LLVMDIBuilderCreateVectorType(Builder: DIBuilderRef,
-                                         Size: c_ulonglong,
-                                         AlignInBits: c_ulonglong,
-                                         Ty: DIType,
-                                         Subscripts: DIArray)
-                                         -> DIType;
-
-    pub fn LLVMDIBuilderGetOrCreateSubrange(Builder: DIBuilderRef,
-                                            Lo: c_longlong,
-                                            Count: c_longlong)
-                                            -> DISubrange;
-
-    pub fn LLVMDIBuilderGetOrCreateArray(Builder: DIBuilderRef,
-                                         Ptr: *const DIDescriptor,
-                                         Count: c_uint)
-                                         -> DIArray;
-
-    pub fn LLVMDIBuilderInsertDeclareAtEnd(Builder: DIBuilderRef,
-                                           Val: ValueRef,
-                                           VarInfo: DIVariable,
-                                           AddrOps: *const i64,
-                                           AddrOpsCount: c_uint,
-                                           DL: ValueRef,
-                                           InsertAtEnd: BasicBlockRef)
-                                           -> ValueRef;
-
-    pub fn LLVMDIBuilderInsertDeclareBefore(Builder: DIBuilderRef,
-                                            Val: ValueRef,
-                                            VarInfo: DIVariable,
-                                            AddrOps: *const i64,
-                                            AddrOpsCount: c_uint,
-                                            DL: ValueRef,
-                                            InsertBefore: ValueRef)
-                                            -> ValueRef;
-
-    pub fn LLVMDIBuilderCreateEnumerator(Builder: DIBuilderRef,
-                                         Name: *const c_char,
-                                         Val: c_ulonglong)
-                                         -> DIEnumerator;
-
-    pub fn LLVMDIBuilderCreateEnumerationType(Builder: DIBuilderRef,
-                                              Scope: DIScope,
-                                              Name: *const c_char,
-                                              File: DIFile,
-                                              LineNumber: c_uint,
-                                              SizeInBits: c_ulonglong,
-                                              AlignInBits: c_ulonglong,
-                                              Elements: DIArray,
-                                              ClassType: DIType)
-                                              -> DIType;
-
-    pub fn LLVMDIBuilderCreateUnionType(Builder: DIBuilderRef,
-                                        Scope: DIScope,
-                                        Name: *const c_char,
-                                        File: DIFile,
-                                        LineNumber: c_uint,
-                                        SizeInBits: c_ulonglong,
-                                        AlignInBits: c_ulonglong,
-                                        Flags: c_uint,
-                                        Elements: DIArray,
-                                        RunTimeLang: c_uint,
-                                        UniqueId: *const c_char)
-                                        -> DIType;
-
-    pub fn LLVMSetUnnamedAddr(GlobalVar: ValueRef, UnnamedAddr: Bool);
-
-    pub fn LLVMDIBuilderCreateTemplateTypeParameter(Builder: DIBuilderRef,
-                                                    Scope: DIScope,
-                                                    Name: *const c_char,
-                                                    Ty: DIType,
-                                                    File: DIFile,
-                                                    LineNo: c_uint,
-                                                    ColumnNo: c_uint)
-                                                    -> DITemplateTypeParameter;
-
-    pub fn LLVMDIBuilderCreateOpDeref() -> i64;
-
-    pub fn LLVMDIBuilderCreateOpPlus() -> i64;
-
-    pub fn LLVMDIBuilderCreateNameSpace(Builder: DIBuilderRef,
-                                        Scope: DIScope,
-                                        Name: *const c_char,
-                                        File: DIFile,
-                                        LineNo: c_uint)
-                                        -> DINameSpace;
-
-    pub fn LLVMDIBuilderCreateDebugLocation(Context: ContextRef,
-                                            Line: c_uint,
-                                            Column: c_uint,
-                                            Scope: DIScope,
-                                            InlinedAt: MetadataRef)
-                                            -> ValueRef;
-
-    pub fn LLVMDICompositeTypeSetTypeArray(Builder: DIBuilderRef,
-                                           CompositeType: DIType,
-                                           TypeArray: DIArray);
-    pub fn LLVMWriteTypeToString(Type: TypeRef, s: RustStringRef);
-    pub fn LLVMWriteValueToString(value_ref: ValueRef, s: RustStringRef);
-
-    pub fn LLVMIsAArgument(value_ref: ValueRef) -> ValueRef;
-
-    pub fn LLVMIsAAllocaInst(value_ref: ValueRef) -> ValueRef;
-    pub fn LLVMIsAConstantInt(value_ref: ValueRef) -> ValueRef;
-
-    pub fn LLVMRustPassKind(Pass: PassRef) -> SupportedPassKind;
-    pub fn LLVMRustFindAndCreatePass(Pass: *const c_char) -> PassRef;
-    pub fn LLVMRustAddPass(PM: PassManagerRef, Pass: PassRef);
-
-    pub fn LLVMRustHasFeature(T: TargetMachineRef,
-                              s: *const c_char) -> bool;
-
-    pub fn LLVMRustCreateTargetMachine(Triple: *const c_char,
-                                       CPU: *const c_char,
-                                       Features: *const c_char,
-                                       Model: CodeGenModel,
-                                       Reloc: RelocMode,
-                                       Level: CodeGenOptLevel,
-                                       UseSoftFP: bool,
-                                       PositionIndependentExecutable: bool,
-                                       FunctionSections: bool,
-                                       DataSections: bool) -> TargetMachineRef;
-    pub fn LLVMRustDisposeTargetMachine(T: TargetMachineRef);
-    pub fn LLVMRustAddAnalysisPasses(T: TargetMachineRef,
-                                     PM: PassManagerRef,
-                                     M: ModuleRef);
-    pub fn LLVMRustAddBuilderLibraryInfo(PMB: PassManagerBuilderRef,
-                                         M: ModuleRef,
-                                         DisableSimplifyLibCalls: bool);
-    pub fn LLVMRustConfigurePassManagerBuilder(PMB: PassManagerBuilderRef,
-                                               OptLevel: CodeGenOptLevel,
-                                               MergeFunctions: bool,
-                                               SLPVectorize: bool,
-                                               LoopVectorize: bool);
-    pub fn LLVMRustAddLibraryInfo(PM: PassManagerRef, M: ModuleRef,
-                                  DisableSimplifyLibCalls: bool);
-    pub fn LLVMRustRunFunctionPassManager(PM: PassManagerRef, M: ModuleRef);
-    pub fn LLVMRustWriteOutputFile(T: TargetMachineRef,
-                                   PM: PassManagerRef,
-                                   M: ModuleRef,
-                                   Output: *const c_char,
-                                   FileType: FileType) -> bool;
-    pub fn LLVMRustPrintModule(PM: PassManagerRef,
-                               M: ModuleRef,
-                               Output: *const c_char);
-    pub fn LLVMRustSetLLVMOptions(Argc: c_int, Argv: *const *const c_char);
-    pub fn LLVMRustPrintPasses();
-    pub fn LLVMRustSetNormalizedTarget(M: ModuleRef, triple: *const c_char);
-    pub fn LLVMRustAddAlwaysInlinePass(P: PassManagerBuilderRef,
-                                       AddLifetimes: bool);
-    pub fn LLVMRustLinkInExternalBitcode(M: ModuleRef,
-                                         bc: *const c_char,
-                                         len: size_t) -> bool;
-    pub fn LLVMRustRunRestrictionPass(M: ModuleRef,
-                                      syms: *const *const c_char,
-                                      len: size_t);
-    pub fn LLVMRustMarkAllFunctionsNounwind(M: ModuleRef);
-
-    pub fn LLVMRustOpenArchive(path: *const c_char) -> ArchiveRef;
-    pub fn LLVMRustArchiveIteratorNew(AR: ArchiveRef) -> ArchiveIteratorRef;
-    pub fn LLVMRustArchiveIteratorNext(AIR: ArchiveIteratorRef) -> ArchiveChildRef;
-    pub fn LLVMRustArchiveChildName(ACR: ArchiveChildRef,
-                                    size: *mut size_t) -> *const c_char;
-    pub fn LLVMRustArchiveChildData(ACR: ArchiveChildRef,
-                                    size: *mut size_t) -> *const c_char;
-    pub fn LLVMRustArchiveChildFree(ACR: ArchiveChildRef);
-    pub fn LLVMRustArchiveIteratorFree(AIR: ArchiveIteratorRef);
-    pub fn LLVMRustDestroyArchive(AR: ArchiveRef);
-
-    pub fn LLVMRustSetDLLStorageClass(V: ValueRef,
-                                      C: DLLStorageClassTypes);
-
-    pub fn LLVMRustGetSectionName(SI: SectionIteratorRef,
-                                  data: *mut *const c_char) -> c_int;
-
-    pub fn LLVMWriteTwineToString(T: TwineRef, s: RustStringRef);
-
-    pub fn LLVMContextSetDiagnosticHandler(C: ContextRef,
-                                           Handler: DiagnosticHandler,
-                                           DiagnosticContext: *mut c_void);
-
-    pub fn LLVMUnpackOptimizationDiagnostic(DI: DiagnosticInfoRef,
-                                            pass_name_out: *mut *const c_char,
-                                            function_out: *mut ValueRef,
-                                            debugloc_out: *mut DebugLocRef,
-                                            message_out: *mut TwineRef);
-    pub fn LLVMUnpackInlineAsmDiagnostic(DI: DiagnosticInfoRef,
-                                            cookie_out: *mut c_uint,
-                                            message_out: *mut TwineRef,
-                                            instruction_out: *mut ValueRef);
-
-    pub fn LLVMWriteDiagnosticInfoToString(DI: DiagnosticInfoRef, s: RustStringRef);
-    pub fn LLVMGetDiagInfoSeverity(DI: DiagnosticInfoRef) -> DiagnosticSeverity;
-    pub fn LLVMGetDiagInfoKind(DI: DiagnosticInfoRef) -> DiagnosticKind;
-
-    pub fn LLVMWriteDebugLocToString(C: ContextRef, DL: DebugLocRef, s: RustStringRef);
-
-    pub fn LLVMSetInlineAsmDiagnosticHandler(C: ContextRef,
-                                             H: InlineAsmDiagHandler,
-                                             CX: *mut c_void);
-
-    pub fn LLVMWriteSMDiagnosticToString(d: SMDiagnosticRef, s: RustStringRef);
-
-    pub fn LLVMRustWriteArchive(Dst: *const c_char,
-                                NumMembers: size_t,
-                                Members: *const RustArchiveMemberRef,
-                                WriteSymbtab: bool,
-                                Kind: ArchiveKind) -> c_int;
-    pub fn LLVMRustArchiveMemberNew(Filename: *const c_char,
-                                    Name: *const c_char,
-                                    Child: ArchiveChildRef) -> RustArchiveMemberRef;
-    pub fn LLVMRustArchiveMemberFree(Member: RustArchiveMemberRef);
-
-    pub fn LLVMRustSetDataLayoutFromTargetMachine(M: ModuleRef,
-                                                  TM: TargetMachineRef);
-    pub fn LLVMRustGetModuleDataLayout(M: ModuleRef) -> TargetDataRef;
-
-    pub fn LLVMRustBuildOperandBundleDef(Name: *const c_char,
-                                         Inputs: *const ValueRef,
-                                         NumInputs: c_uint)
-                                         -> OperandBundleDefRef;
-    pub fn LLVMRustFreeOperandBundleDef(Bundle: OperandBundleDefRef);
-
-    pub fn LLVMRustPositionBuilderAtStart(B: BuilderRef, BB: BasicBlockRef);
-
-    pub fn LLVMRustSetComdat(M: ModuleRef, V: ValueRef, Name: *const c_char);
-    pub fn LLVMRustUnsetComdat(V: ValueRef);
-}
-
-// LLVM requires symbols from this library, but apparently they're not printed
-// during llvm-config?
-#[cfg(windows)]
-#[link(name = "ole32")]
-extern {}
-
 pub fn SetInstructionCallConv(instr: ValueRef, cc: CallConv) {
     unsafe {
         LLVMSetInstructionCallConv(instr, cc as c_uint);
@@ -2173,11 +200,6 @@
         LLVMSetFunctionCallConv(fn_, cc as c_uint);
     }
 }
-pub fn SetLinkage(global: ValueRef, link: Linkage) {
-    unsafe {
-        LLVMSetLinkage(global, link as c_uint);
-    }
-}
 
 // Externally visible symbols that might appear in multiple translation units need to appear in
 // their own comdat section so that the duplicates can be discarded at link time. This can for
@@ -2197,12 +219,6 @@
     }
 }
 
-pub fn SetDLLStorageClass(global: ValueRef, class: DLLStorageClassTypes) {
-    unsafe {
-        LLVMRustSetDLLStorageClass(global, class);
-    }
-}
-
 pub fn SetUnnamedAddr(global: ValueRef, unnamed: bool) {
     unsafe {
         LLVMSetUnnamedAddr(global, unnamed as Bool);
@@ -2215,29 +231,40 @@
     }
 }
 
-pub fn ConstICmp(pred: IntPredicate, v1: ValueRef, v2: ValueRef) -> ValueRef {
-    unsafe {
-        LLVMConstICmp(pred as c_ushort, v1, v2)
+impl Attribute {
+    pub fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef) {
+        unsafe {
+            LLVMRustAddFunctionAttribute(
+                llfn, idx.as_uint(), self.bits())
+        }
     }
-}
-pub fn ConstFCmp(pred: RealPredicate, v1: ValueRef, v2: ValueRef) -> ValueRef {
-    unsafe {
-        LLVMConstFCmp(pred as c_ushort, v1, v2)
-    }
-}
 
-pub fn SetFunctionAttribute(fn_: ValueRef, attr: Attribute) {
-    unsafe {
-        LLVMAddFunctionAttribute(fn_, FunctionIndex as c_uint,
-                                 attr.bits() as uint64_t)
+    pub fn apply_callsite(&self, idx: AttributePlace, callsite: ValueRef) {
+        unsafe {
+            LLVMRustAddCallSiteAttribute(
+                callsite, idx.as_uint(), self.bits())
+        }
     }
-}
 
-pub fn RemoveFunctionAttributes(fn_: ValueRef, attr: Attribute) {
-    unsafe {
-        LLVMRemoveFunctionAttributes(fn_, FunctionIndex as c_uint,
-                                           attr.bits() as uint64_t)
+    pub fn unapply_llfn(&self, idx: AttributePlace, llfn: ValueRef) {
+        unsafe {
+            LLVMRustRemoveFunctionAttributes(
+                llfn, idx.as_uint(), self.bits())
+        }
     }
+
+    pub fn toggle_llfn(&self,
+                       idx: AttributePlace,
+                       llfn: ValueRef,
+                       set: bool)
+    {
+        if set {
+            self.apply_llfn(idx, llfn);
+        } else {
+            self.unapply_llfn(idx, llfn);
+        }
+    }
+
 }
 
 /* Memory-managed interface to target data. */
@@ -2334,22 +361,6 @@
     }
 }
 
-#[allow(missing_copy_implementations)]
-pub enum RustString_opaque {}
-pub type RustStringRef = *mut RustString_opaque;
-type RustStringRepr = *mut RefCell<Vec<u8>>;
-
-/// Appending to a Rust string -- used by raw_rust_string_ostream.
-#[no_mangle]
-pub unsafe extern "C" fn rust_llvm_string_write_impl(sr: RustStringRef,
-                                                     ptr: *const c_char,
-                                                     size: size_t) {
-    let slice = slice::from_raw_parts(ptr as *const u8, size as usize);
-
-    let sr = sr as RustStringRepr;
-    (*sr).borrow_mut().extend_from_slice(slice);
-}
-
 pub fn build_string<F>(f: F) -> Option<String> where F: FnOnce(RustStringRef){
     let mut buf = RefCell::new(Vec::new());
     f(&mut buf as RustStringRepr as RustStringRef);
@@ -2357,12 +368,12 @@
 }
 
 pub unsafe fn twine_to_string(tr: TwineRef) -> String {
-    build_string(|s| LLVMWriteTwineToString(tr, s))
+    build_string(|s| LLVMRustWriteTwineToString(tr, s))
         .expect("got a non-UTF8 Twine from LLVM")
 }
 
 pub unsafe fn debug_loc_to_string(c: ContextRef, tr: DebugLocRef) -> String {
-    build_string(|s| LLVMWriteDebugLocToString(c, tr, s))
+    build_string(|s| LLVMRustWriteDebugLocToString(c, tr, s))
         .expect("got a non-UTF8 DebugLoc from LLVM")
 }
 
diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs
index 2e8c5a7..c39ad41 100644
--- a/src/librustc_metadata/astencode.rs
+++ b/src/librustc_metadata/astencode.rs
@@ -18,7 +18,7 @@
 use rustc::hir;
 use rustc::hir::fold;
 use rustc::hir::fold::Folder;
-use rustc::hir::intravisit::{IdRange, IdRangeComputingVisitor, IdVisitingOperation};
+use rustc::hir::intravisit::{Visitor, IdRangeComputingVisitor, IdRange};
 
 use common as c;
 use cstore;
@@ -88,8 +88,9 @@
            rbml_w.writer.seek(SeekFrom::Current(0)));
 
     // Folding could be avoided with a smarter encoder.
-    let ii = simplify_ast(ii);
+    let (ii, expected_id_range) = simplify_ast(ii);
     let id_range = inlined_item_id_range(&ii);
+    assert_eq!(expected_id_range, id_range);
 
     rbml_w.start_tag(c::tag_ast as usize);
     id_range.encode(rbml_w);
@@ -186,6 +187,10 @@
     pub fn tr_id(&self, id: ast::NodeId) -> ast::NodeId {
         // from_id_range should be non-empty
         assert!(!self.from_id_range.empty());
+        // Make sure that translating the NodeId will actually yield a
+        // meaningful result
+        assert!(self.from_id_range.contains(id));
+
         // Use wrapping arithmetic because otherwise it introduces control flow.
         // Maybe we should just have the control flow? -- aatch
         (id.wrapping_sub(self.from_id_range.min).wrapping_add(self.to_id_range.min))
@@ -279,9 +284,23 @@
     rbml_w.end_tag();
 }
 
-struct NestedItemsDropper;
+struct NestedItemsDropper {
+    id_range: IdRange
+}
 
 impl Folder for NestedItemsDropper {
+
+    // The unit tests below run on HIR with NodeIds not properly assigned. That
+    // causes an integer overflow. So we just don't track the id_range when
+    // building the unit tests.
+    #[cfg(not(test))]
+    fn new_id(&mut self, id: ast::NodeId) -> ast::NodeId {
+        // Record the range of NodeIds we are visiting, so we can do a sanity
+        // check later
+        self.id_range.add(id);
+        id
+    }
+
     fn fold_block(&mut self, blk: P<hir::Block>) -> P<hir::Block> {
         blk.and_then(|hir::Block {id, stmts, expr, rules, span, ..}| {
             let stmts_sans_items = stmts.into_iter().filter_map(|stmt| {
@@ -322,10 +341,12 @@
 // As it happens, trans relies on the fact that we do not export
 // nested items, as otherwise it would get confused when translating
 // inlined items.
-fn simplify_ast(ii: InlinedItemRef) -> InlinedItem {
-    let mut fld = NestedItemsDropper;
+fn simplify_ast(ii: InlinedItemRef) -> (InlinedItem, IdRange) {
+    let mut fld = NestedItemsDropper {
+        id_range: IdRange::max()
+    };
 
-    match ii {
+    let ii = match ii {
         // HACK we're not dropping items.
         InlinedItemRef::Item(i) => {
             InlinedItem::Item(P(fold::noop_fold_item(i.clone(), &mut fld)))
@@ -339,7 +360,9 @@
         InlinedItemRef::Foreign(i) => {
             InlinedItem::Foreign(P(fold::noop_fold_foreign_item(i.clone(), &mut fld)))
         }
-    }
+    };
+
+    (ii, fld.id_range)
 }
 
 fn decode_ast(item_doc: rbml::Doc) -> InlinedItem {
@@ -361,8 +384,18 @@
         match *self {
           Def::Fn(did) => Def::Fn(did.tr(dcx)),
           Def::Method(did) => Def::Method(did.tr(dcx)),
-          Def::SelfTy(opt_did, impl_id) => { Def::SelfTy(opt_did.map(|did| did.tr(dcx)),
-                                                         impl_id.map(|id| dcx.tr_id(id))) }
+          Def::SelfTy(opt_did, impl_id) => {
+              // Since the impl_id will never lie within the reserved range of
+              // imported NodeIds, it does not make sense to translate it.
+              // The result would not make any sense within the importing crate.
+              // We also don't allow for impl items to be inlined (just their
+              // members), so even if we had a DefId here, we wouldn't be able
+              // to do much with it.
+              // So, we set the id to DUMMY_NODE_ID. That way we make it
+              // explicit that this is no usable NodeId.
+              Def::SelfTy(opt_did.map(|did| did.tr(dcx)),
+                          impl_id.map(|_| ast::DUMMY_NODE_ID))
+          }
           Def::Mod(did) => { Def::Mod(did.tr(dcx)) }
           Def::ForeignMod(did) => { Def::ForeignMod(did.tr(dcx)) }
           Def::Static(did, m) => { Def::Static(did.tr(dcx), m) }
@@ -693,7 +726,7 @@
     rbml_w: &'a mut Encoder<'b>,
 }
 
-impl<'a, 'b, 'c, 'tcx> IdVisitingOperation for
+impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for
         SideTableEncodingIdVisitor<'a, 'b, 'c, 'tcx> {
     fn visit_id(&mut self, id: ast::NodeId) {
         encode_side_tables_for_id(self.ecx, self.rbml_w, id)
@@ -704,7 +737,7 @@
                              rbml_w: &mut Encoder,
                              ii: &InlinedItem) {
     rbml_w.start_tag(c::tag_table as usize);
-    ii.visit_ids(&mut SideTableEncodingIdVisitor {
+    ii.visit(&mut SideTableEncodingIdVisitor {
         ecx: ecx,
         rbml_w: rbml_w
     });
@@ -1242,9 +1275,9 @@
     }
 }
 
-fn inlined_item_id_range(v: &InlinedItem) -> IdRange {
+fn inlined_item_id_range(ii: &InlinedItem) -> IdRange {
     let mut visitor = IdRangeComputingVisitor::new();
-    v.visit_ids(&mut visitor);
+    ii.visit(&mut visitor);
     visitor.result()
 }
 
@@ -1361,7 +1394,7 @@
     with_testing_context(|lcx| {
         let hir_item = lcx.lower_item(&item);
         let item_in = InlinedItemRef::Item(&hir_item);
-        let item_out = simplify_ast(item_in);
+        let (item_out, _) = simplify_ast(item_in);
         let item_exp = InlinedItem::Item(P(lcx.lower_item(&quote_item!(&cx,
             fn new_int_alist<B>() -> alist<isize, B> {
                 return alist {eq_fn: eq_int, data: Vec::new()};
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index d4443c6..0b60fc3 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -243,7 +243,7 @@
 
         // Check for (potential) conflicts with the local crate
         if self.local_crate_name == crate_name &&
-           self.sess.crate_disambiguator.get().as_str() == disambiguator {
+           self.sess.local_crate_disambiguator() == disambiguator {
             span_fatal!(self.sess, span, E0519,
                         "the current crate is indistinguishable from one of its \
                          dependencies: it has the same crate-name `{}` and was \
diff --git a/src/librustc_metadata/csearch.rs b/src/librustc_metadata/csearch.rs
index 850d6c9..862245b 100644
--- a/src/librustc_metadata/csearch.rs
+++ b/src/librustc_metadata/csearch.rs
@@ -14,7 +14,7 @@
 use encoder;
 use loader;
 
-use middle::cstore::{CrateStore, CrateSource, ChildItem, ExternCrate, FoundAst, DefLike};
+use middle::cstore::{InlinedItem, CrateStore, CrateSource, ChildItem, ExternCrate, DefLike};
 use middle::cstore::{NativeLibraryKind, LinkMeta, LinkagePreference};
 use rustc::hir::def;
 use middle::lang_items;
@@ -482,12 +482,146 @@
         result
     }
 
-    fn maybe_get_item_ast<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-                              -> FoundAst<'tcx>
+    fn maybe_get_item_ast<'a>(&'tcx self,
+                              tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                              def_id: DefId)
+                              -> Option<(&'tcx InlinedItem, ast::NodeId)>
     {
-        self.dep_graph.read(DepNode::MetaData(def));
-        let cdata = self.get_crate_data(def.krate);
-        decoder::maybe_get_item_ast(&cdata, tcx, def.index)
+        self.dep_graph.read(DepNode::MetaData(def_id));
+
+        match self.inlined_item_cache.borrow().get(&def_id) {
+            Some(&None) => {
+                return None; // Not inlinable
+            }
+            Some(&Some(ref cached_inlined_item)) => {
+                // Already inline
+                debug!("maybe_get_item_ast({}): already inline as node id {}",
+                          tcx.item_path_str(def_id), cached_inlined_item.item_id);
+                return Some((tcx.map.expect_inlined_item(cached_inlined_item.inlined_root),
+                             cached_inlined_item.item_id));
+            }
+            None => {
+                // Not seen yet
+            }
+        }
+
+        debug!("maybe_get_item_ast({}): inlining item", tcx.item_path_str(def_id));
+
+        let cdata = self.get_crate_data(def_id.krate);
+        let inlined = decoder::maybe_get_item_ast(&cdata, tcx, def_id.index);
+
+        let cache_inlined_item = |original_def_id, inlined_item_id, inlined_root_node_id| {
+            let cache_entry = cstore::CachedInlinedItem {
+                inlined_root: inlined_root_node_id,
+                item_id: inlined_item_id,
+            };
+            self.inlined_item_cache
+                .borrow_mut()
+                .insert(original_def_id, Some(cache_entry));
+            self.defid_for_inlined_node
+                .borrow_mut()
+                .insert(inlined_item_id, original_def_id);
+        };
+
+        let find_inlined_item_root = |inlined_item_id| {
+            let mut node = inlined_item_id;
+            let mut path = Vec::with_capacity(10);
+
+            // If we can't find the inline root after a thousand hops, we can
+            // be pretty sure there's something wrong with the HIR map.
+            for _ in 0 .. 1000 {
+                path.push(node);
+                let parent_node = tcx.map.get_parent_node(node);
+                if parent_node == node {
+                    return node;
+                }
+                node = parent_node;
+            }
+            bug!("cycle in HIR map parent chain")
+        };
+
+        match inlined {
+            decoder::FoundAst::NotFound => {
+                self.inlined_item_cache
+                    .borrow_mut()
+                    .insert(def_id, None);
+            }
+            decoder::FoundAst::Found(&InlinedItem::Item(ref item)) => {
+                let inlined_root_node_id = find_inlined_item_root(item.id);
+                cache_inlined_item(def_id, item.id, inlined_root_node_id);
+            }
+            decoder::FoundAst::Found(&InlinedItem::Foreign(ref item)) => {
+                let inlined_root_node_id = find_inlined_item_root(item.id);
+                cache_inlined_item(def_id, item.id, inlined_root_node_id);
+            }
+            decoder::FoundAst::FoundParent(parent_did, item) => {
+                let inlined_root_node_id = find_inlined_item_root(item.id);
+                cache_inlined_item(parent_did, item.id, inlined_root_node_id);
+
+                match item.node {
+                    hir::ItemEnum(ref ast_def, _) => {
+                        let ast_vs = &ast_def.variants;
+                        let ty_vs = &tcx.lookup_adt_def(parent_did).variants;
+                        assert_eq!(ast_vs.len(), ty_vs.len());
+                        for (ast_v, ty_v) in ast_vs.iter().zip(ty_vs.iter()) {
+                            cache_inlined_item(ty_v.did,
+                                               ast_v.node.data.id(),
+                                               inlined_root_node_id);
+                        }
+                    }
+                    hir::ItemStruct(ref struct_def, _) => {
+                        if struct_def.is_struct() {
+                            bug!("instantiate_inline: called on a non-tuple struct")
+                        } else {
+                            cache_inlined_item(def_id,
+                                               struct_def.id(),
+                                               inlined_root_node_id);
+                        }
+                    }
+                    _ => bug!("instantiate_inline: item has a \
+                               non-enum, non-struct parent")
+                }
+            }
+            decoder::FoundAst::Found(&InlinedItem::TraitItem(_, ref trait_item)) => {
+                let inlined_root_node_id = find_inlined_item_root(trait_item.id);
+                cache_inlined_item(def_id, trait_item.id, inlined_root_node_id);
+
+                // Associated consts already have to be evaluated in `typeck`, so
+                // the logic to do that already exists in `middle`. In order to
+                // reuse that code, it needs to be able to look up the traits for
+                // inlined items.
+                let ty_trait_item = tcx.impl_or_trait_item(def_id).clone();
+                let trait_item_def_id = tcx.map.local_def_id(trait_item.id);
+                tcx.impl_or_trait_items.borrow_mut()
+                   .insert(trait_item_def_id, ty_trait_item);
+            }
+            decoder::FoundAst::Found(&InlinedItem::ImplItem(_, ref impl_item)) => {
+                let inlined_root_node_id = find_inlined_item_root(impl_item.id);
+                cache_inlined_item(def_id, impl_item.id, inlined_root_node_id);
+            }
+        }
+
+        // We can be sure to hit the cache now
+        return self.maybe_get_item_ast(tcx, def_id);
+    }
+
+    fn local_node_for_inlined_defid(&'tcx self, def_id: DefId) -> Option<ast::NodeId> {
+        assert!(!def_id.is_local());
+        match self.inlined_item_cache.borrow().get(&def_id) {
+            Some(&Some(ref cached_inlined_item)) => {
+                Some(cached_inlined_item.item_id)
+            }
+            Some(&None) => {
+                None
+            }
+            _ => {
+                bug!("Trying to lookup inlined NodeId for unexpected item");
+            }
+        }
+    }
+
+    fn defid_for_inlined_node(&'tcx self, node_id: ast::NodeId) -> Option<DefId> {
+        self.defid_for_inlined_node.borrow().get(&node_id).map(|x| *x)
     }
 
     fn maybe_get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
@@ -634,3 +768,4 @@
         visible_parent_map
     }
 }
+
diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs
index 6baa0ac..d786cc5 100644
--- a/src/librustc_metadata/cstore.rs
+++ b/src/librustc_metadata/cstore.rs
@@ -25,7 +25,7 @@
 use rustc::hir::def_id::{DefIndex, DefId};
 use rustc::hir::map::DefKey;
 use rustc::hir::svh::Svh;
-use rustc::middle::cstore::{ExternCrate};
+use rustc::middle::cstore::ExternCrate;
 use rustc::session::config::PanicStrategy;
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet, DefIdMap};
@@ -96,6 +96,13 @@
     pub explicitly_linked: Cell<bool>,
 }
 
+pub struct CachedInlinedItem {
+    /// The NodeId of the RootInlinedParent HIR map entry
+    pub inlined_root: ast::NodeId,
+    /// The local NodeId of the inlined entity
+    pub item_id: ast::NodeId,
+}
+
 pub struct CStore {
     pub dep_graph: DepGraph,
     metas: RefCell<FnvHashMap<ast::CrateNum, Rc<CrateMetadata>>>,
@@ -105,6 +112,8 @@
     used_libraries: RefCell<Vec<(String, NativeLibraryKind)>>,
     used_link_args: RefCell<Vec<String>>,
     statically_included_foreign_items: RefCell<NodeSet>,
+    pub inlined_item_cache: RefCell<DefIdMap<Option<CachedInlinedItem>>>,
+    pub defid_for_inlined_node: RefCell<NodeMap<DefId>>,
     pub visible_parent_map: RefCell<DefIdMap<DefId>>,
 }
 
@@ -119,6 +128,8 @@
             used_link_args: RefCell::new(Vec::new()),
             statically_included_foreign_items: RefCell::new(NodeSet()),
             visible_parent_map: RefCell::new(FnvHashMap()),
+            inlined_item_cache: RefCell::new(FnvHashMap()),
+            defid_for_inlined_node: RefCell::new(FnvHashMap()),
         }
     }
 
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 409cec2..d8fd25d 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -30,7 +30,7 @@
 use rustc::hir;
 use rustc::session::config::PanicStrategy;
 
-use middle::cstore::{FoundAst, InlinedItem, LinkagePreference};
+use middle::cstore::{InlinedItem, LinkagePreference};
 use middle::cstore::{DefLike, DlDef, DlField, DlImpl, tls};
 use rustc::hir::def::Def;
 use rustc::hir::def_id::{DefId, DefIndex};
@@ -55,7 +55,6 @@
 use syntax::attr;
 use syntax::parse::token;
 use syntax::ast;
-use syntax::abi::Abi;
 use syntax::codemap;
 use syntax::print::pprust;
 use syntax::ptr::P;
@@ -756,6 +755,12 @@
     maybe_item_name(cdata.lookup_item(id))
 }
 
+pub enum FoundAst<'ast> {
+    Found(&'ast InlinedItem),
+    FoundParent(DefId, &'ast hir::Item),
+    NotFound,
+}
+
 pub fn maybe_get_item_ast<'a, 'tcx>(cdata: Cmd, tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefIndex)
                                     -> FoundAst<'tcx> {
     debug!("Looking up item: {:?}", id);
@@ -1160,15 +1165,7 @@
                 // an attribute
                 assert_eq!(meta_items.len(), 1);
                 let meta_item = meta_items.into_iter().nth(0).unwrap();
-                codemap::Spanned {
-                    node: ast::Attribute_ {
-                        id: attr::mk_attr_id(),
-                        style: ast::AttrStyle::Outer,
-                        value: meta_item,
-                        is_sugared_doc: is_sugared_doc,
-                    },
-                    span: syntax_pos::DUMMY_SP
-                }
+                attr::mk_doc_attr_outer(attr::mk_attr_id(), meta_item, is_sugared_doc)
             }).collect()
         },
         None => vec![],
@@ -1542,13 +1539,9 @@
     let applicable = match item_family(item_doc) {
         ImmStatic | MutStatic => true,
         Fn => {
-            let ty::TypeScheme { generics, ty } = get_type(cdata, id, tcx);
+            let ty::TypeScheme { generics, .. } = get_type(cdata, id, tcx);
             let no_generics = generics.types.is_empty();
-            match ty.sty {
-                ty::TyFnDef(_, _, fn_ty) | ty::TyFnPtr(fn_ty)
-                    if fn_ty.abi != Abi::Rust => return no_generics,
-                _ => no_generics,
-            }
+            no_generics
         },
         _ => false,
     };
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index 7314259..732c256 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -44,7 +44,7 @@
 use std::u32;
 use syntax::abi::Abi;
 use syntax::ast::{self, NodeId, Name, CRATE_NODE_ID, CrateNum};
-use syntax::attr;
+use syntax::attr::{self,AttrMetaMethods,AttributeMethods};
 use errors::Handler;
 use syntax;
 use syntax_pos::BytePos;
@@ -1431,31 +1431,28 @@
 }
 
 fn encode_meta_item(rbml_w: &mut Encoder, mi: &ast::MetaItem) {
-    match mi.node {
-      ast::MetaItemKind::Word(ref name) => {
+    if mi.is_word() {
+        let name = mi.name();
         rbml_w.start_tag(tag_meta_item_word);
-        rbml_w.wr_tagged_str(tag_meta_item_name, name);
+        rbml_w.wr_tagged_str(tag_meta_item_name, &name);
         rbml_w.end_tag();
-      }
-      ast::MetaItemKind::NameValue(ref name, ref value) => {
-        match value.node {
-          ast::LitKind::Str(ref value, _) => {
-            rbml_w.start_tag(tag_meta_item_name_value);
-            rbml_w.wr_tagged_str(tag_meta_item_name, name);
-            rbml_w.wr_tagged_str(tag_meta_item_value, value);
-            rbml_w.end_tag();
-          }
-          _ => {/* FIXME (#623): encode other variants */ }
-        }
-      }
-      ast::MetaItemKind::List(ref name, ref items) => {
+    } else if mi.is_value_str() {
+        let name = mi.name();
+        /* FIXME (#623): support other literal kinds */
+        let value = mi.value_str().unwrap();
+        rbml_w.start_tag(tag_meta_item_name_value);
+        rbml_w.wr_tagged_str(tag_meta_item_name, &name);
+        rbml_w.wr_tagged_str(tag_meta_item_value, &value);
+        rbml_w.end_tag();
+    } else { // it must be a list
+        let name = mi.name();
+        let items = mi.meta_item_list().unwrap();
         rbml_w.start_tag(tag_meta_item_list);
-        rbml_w.wr_tagged_str(tag_meta_item_name, name);
+        rbml_w.wr_tagged_str(tag_meta_item_name, &name);
         for inner_item in items {
             encode_meta_item(rbml_w, &inner_item);
         }
         rbml_w.end_tag();
-      }
     }
 }
 
@@ -1464,7 +1461,7 @@
     for attr in attrs {
         rbml_w.start_tag(tag_attribute);
         rbml_w.wr_tagged_u8(tag_attribute_is_sugared_doc, attr.node.is_sugared_doc as u8);
-        encode_meta_item(rbml_w, &attr.node.value);
+        encode_meta_item(rbml_w, attr.meta());
         rbml_w.end_tag();
     }
     rbml_w.end_tag();
@@ -1893,7 +1890,7 @@
     encode_crate_name(rbml_w, &ecx.link_meta.crate_name);
     encode_crate_triple(rbml_w, &ecx.tcx.sess.opts.target_triple);
     encode_hash(rbml_w, &ecx.link_meta.crate_hash);
-    encode_crate_disambiguator(rbml_w, &ecx.tcx.sess.crate_disambiguator.get().as_str());
+    encode_crate_disambiguator(rbml_w, &ecx.tcx.sess.local_crate_disambiguator());
     encode_dylib_dependency_formats(rbml_w, &ecx);
     encode_panic_strategy(rbml_w, &ecx);
 
diff --git a/src/librustc_metadata/macro_import.rs b/src/librustc_metadata/macro_import.rs
index 7dadf8d..4be044c 100644
--- a/src/librustc_metadata/macro_import.rs
+++ b/src/librustc_metadata/macro_import.rs
@@ -60,10 +60,10 @@
                     }
                     if let (Some(sel), Some(names)) = (import.as_mut(), names) {
                         for attr in names {
-                            if let ast::MetaItemKind::Word(ref name) = attr.node {
-                                sel.insert(name.clone(), attr.span);
+                            if attr.is_word() {
+                                sel.insert(attr.name().clone(), attr.span());
                             } else {
-                                span_err!(self.sess, attr.span, E0466, "bad macro import");
+                                span_err!(self.sess, attr.span(), E0466, "bad macro import");
                             }
                         }
                     }
@@ -78,10 +78,10 @@
                     };
 
                     for attr in names {
-                        if let ast::MetaItemKind::Word(ref name) = attr.node {
-                            reexport.insert(name.clone(), attr.span);
+                        if attr.is_word() {
+                            reexport.insert(attr.name().clone(), attr.span());
                         } else {
-                            call_bad_macro_reexport(self.sess, attr.span);
+                            call_bad_macro_reexport(self.sess, attr.span());
                         }
                     }
                 }
diff --git a/src/librustc_mir/mir_map.rs b/src/librustc_mir/mir_map.rs
index b7c5f35..11d6b07 100644
--- a/src/librustc_mir/mir_map.rs
+++ b/src/librustc_mir/mir_map.rs
@@ -250,7 +250,7 @@
             build::construct_fn(cx, id, arguments, fn_sig.output, body)
         });
 
-        intravisit::walk_fn(self, fk, decl, body, span);
+        intravisit::walk_fn(self, fk, decl, body, span, id);
     }
 }
 
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index a90b563..d2cf48e 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -55,6 +55,17 @@
             err.emit();
         }
     }
+
+    fn check_decl_no_pat<ReportFn: Fn(Span, bool)>(&self, decl: &FnDecl, report_err: ReportFn) {
+        for arg in &decl.inputs {
+            match arg.pat.node {
+                PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), _, None) |
+                PatKind::Wild => {}
+                PatKind::Ident(..) => report_err(arg.pat.span, true),
+                _ => report_err(arg.pat.span, false),
+            }
+        }
+    }
 }
 
 impl<'a> Visitor for AstValidator<'a> {
@@ -82,6 +93,23 @@
         visit::walk_expr(self, expr)
     }
 
+    fn visit_ty(&mut self, ty: &Ty) {
+        match ty.node {
+            TyKind::BareFn(ref bfty) => {
+                self.check_decl_no_pat(&bfty.decl, |span, _| {
+                    let mut err = struct_span_err!(self.session, span, E0561,
+                                            "patterns aren't allowed in function pointer types");
+                    err.span_note(span, "this is a recent error, see \
+                                         issue #35203 for more details");
+                    err.emit();
+                });
+            }
+            _ => {}
+        }
+
+        visit::walk_ty(self, ty)
+    }
+
     fn visit_path(&mut self, path: &Path, id: NodeId) {
         if path.global && path.segments.len() > 0 {
             let ident = path.segments[0].identifier;
@@ -135,6 +163,25 @@
         visit::walk_item(self, item)
     }
 
+    fn visit_foreign_item(&mut self, fi: &ForeignItem) {
+        match fi.node {
+            ForeignItemKind::Fn(ref decl, _) => {
+                self.check_decl_no_pat(decl, |span, is_recent| {
+                    let mut err = struct_span_err!(self.session, span, E0130,
+                                        "patterns aren't allowed in foreign function declarations");
+                    if is_recent {
+                        err.span_note(span, "this is a recent error, see \
+                                             issue #35203 for more details");
+                    }
+                    err.emit();
+                });
+            }
+            ForeignItemKind::Static(..) => {}
+        }
+
+        visit::walk_foreign_item(self, fi)
+    }
+
     fn visit_variant_data(&mut self, vdata: &VariantData, _: Ident,
                           _: &Generics, _: NodeId, span: Span) {
         if vdata.fields().is_empty() {
diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs
index 27ce03b..1030a4b 100644
--- a/src/librustc_passes/consts.rs
+++ b/src/librustc_passes/consts.rs
@@ -40,6 +40,7 @@
 use rustc::middle::mem_categorization::Categorization;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::traits::ProjectionMode;
+use rustc::util::common::ErrorReported;
 use rustc::util::nodemap::NodeMap;
 use rustc::middle::const_qualif::ConstQualif;
 use rustc::lint::builtin::CONST_ERR;
@@ -116,7 +117,7 @@
                 _ => self.tcx.sess.add_lint(CONST_ERR, expr.id, expr.span,
                                          format!("constant evaluation error: {}. This will \
                                                  become a HARD ERROR in the future",
-                                                 err.description())),
+                                                 err.description().into_oneline())),
             }
         }
         self.with_mode(mode, |this| {
@@ -157,7 +158,7 @@
 
         let qualif = self.with_mode(mode, |this| {
             this.with_euv(Some(fn_id), |euv| euv.walk_fn(fd, b));
-            intravisit::walk_fn(this, fk, fd, b, s);
+            intravisit::walk_fn(this, fk, fd, b, s, fn_id);
             this.qualif
         });
 
@@ -211,15 +212,6 @@
             }
         }
     }
-
-    fn msg(&self) -> &'static str {
-        match self.mode {
-            Mode::Const => "constant",
-            Mode::ConstFn => "constant function",
-            Mode::StaticMut | Mode::Static => "static",
-            Mode::Var => bug!(),
-        }
-    }
 }
 
 impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
@@ -289,18 +281,14 @@
                 self.global_expr(Mode::Const, &start);
                 self.global_expr(Mode::Const, &end);
 
-                match compare_lit_exprs(self.tcx, start, end) {
-                    Some(Ordering::Less) |
-                    Some(Ordering::Equal) => {}
-                    Some(Ordering::Greater) => {
+                match compare_lit_exprs(self.tcx, p.span, start, end) {
+                    Ok(Ordering::Less) |
+                    Ok(Ordering::Equal) => {}
+                    Ok(Ordering::Greater) => {
                         span_err!(self.tcx.sess, start.span, E0030,
                             "lower range bound must be less than or equal to upper");
                     }
-                    None => {
-                        span_err!(self.tcx.sess, p.span, E0014,
-                                  "paths in {}s may only refer to constants",
-                                  self.msg());
-                    }
+                    Err(ErrorReported) => {}
                 }
             }
             _ => intravisit::walk_pat(self, p)
@@ -429,7 +417,7 @@
                 Err(msg) => {
                     self.tcx.sess.add_lint(CONST_ERR, ex.id,
                                            msg.span,
-                                           msg.description().into_owned())
+                                           msg.description().into_oneline().into_owned())
                 }
             }
         }
diff --git a/src/librustc_passes/diagnostics.rs b/src/librustc_passes/diagnostics.rs
index 918e17d..3e2dd47 100644
--- a/src/librustc_passes/diagnostics.rs
+++ b/src/librustc_passes/diagnostics.rs
@@ -11,7 +11,7 @@
 #![allow(non_snake_case)]
 
 register_long_diagnostics! {
-
+/*
 E0014: r##"
 Constants can only be initialized by a constant value or, in a future
 version of Rust, a call to a const function. This error indicates the use
@@ -30,7 +30,7 @@
 const FOO2: i32 = { 0 }; // but brackets are useless here
 ```
 "##,
-
+*/
 E0030: r##"
 When matching against a range, the compiler verifies that the range is
 non-empty.  Range patterns include both end-points, so this is equivalent to
@@ -49,6 +49,39 @@
 ```
 "##,
 
+E0130: r##"
+You declared a pattern as an argument in a foreign function declaration.
+Erroneous code example:
+
+```compile_fail
+extern {
+    fn foo((a, b): (u32, u32)); // error: patterns aren't allowed in foreign
+                                //        function declarations
+}
+```
+
+Please replace the pattern argument with a regular one. Example:
+
+```
+struct SomeStruct {
+    a: u32,
+    b: u32,
+}
+
+extern {
+    fn foo(s: SomeStruct); // ok!
+}
+```
+
+Or:
+
+```
+extern {
+    fn foo(a: (u32, u32)); // ok!
+}
+```
+"##,
+
 E0161: r##"
 A value was moved. However, its size was not known at compile time, and only
 values of a known size can be moved.
@@ -187,4 +220,5 @@
 
 register_diagnostics! {
     E0472, // asm! is unsupported on this target
+    E0561, // patterns aren't allowed in function pointer types
 }
diff --git a/src/librustc_passes/rvalues.rs b/src/librustc_passes/rvalues.rs
index 4684683..2a5dc50 100644
--- a/src/librustc_passes/rvalues.rs
+++ b/src/librustc_passes/rvalues.rs
@@ -49,7 +49,7 @@
             let mut euv = euv::ExprUseVisitor::new(&mut delegate, &infcx);
             euv.walk_fn(fd, b);
         });
-        intravisit::walk_fn(self, fk, fd, b, s)
+        intravisit::walk_fn(self, fk, fd, b, s, fn_id)
     }
 }
 
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index acaf9b9..793e52d 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -291,7 +291,7 @@
             }
         }
 
-        intravisit::walk_mod(self, m);
+        intravisit::walk_mod(self, m, id);
     }
 
     fn visit_macro_def(&mut self, md: &'v hir::MacroDef) {
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index aa8c706..c1511b2 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -825,8 +825,6 @@
     Import {
         binding: &'a NameBinding<'a>,
         directive: &'a ImportDirective<'a>,
-        // Some(error) if using this imported name causes the import to be a privacy error
-        privacy_error: Option<Box<PrivacyError<'a>>>,
     },
 }
 
@@ -1206,16 +1204,11 @@
             self.used_crates.insert(krate);
         }
 
-        let (directive, privacy_error) = match binding.kind {
-            NameBindingKind::Import { directive, ref privacy_error, .. } =>
-                (directive, privacy_error),
+        let directive = match binding.kind {
+            NameBindingKind::Import { directive, .. } => directive,
             _ => return,
         };
 
-        if let Some(error) = privacy_error.as_ref() {
-            self.privacy_errors.push((**error).clone());
-        }
-
         if !self.make_glob_map {
             return;
         }
@@ -1814,39 +1807,25 @@
                                path_depth: usize)
                                -> Result<PathResolution, ()> {
         self.resolve_path(id, trait_path, path_depth, TypeNS).and_then(|path_res| {
-            if let Def::Trait(_) = path_res.base_def {
-                debug!("(resolving trait) found trait def: {:?}", path_res);
-                Ok(path_res)
-            } else {
-                let mut err =
-                    resolve_struct_error(self,
-                                  trait_path.span,
-                                  ResolutionError::IsNotATrait(&path_names_to_string(trait_path,
-                                                                                      path_depth)));
-
-                // If it's a typedef, give a note
-                if let Def::TyAlias(..) = path_res.base_def {
-                    let trait_name = trait_path.segments.last().unwrap().identifier.name;
-                    err.span_label(trait_path.span,
-                                   &format!("`{}` is not a trait", trait_name));
-
-                    let definition_site = {
-                        let segments = &trait_path.segments;
-                        if trait_path.global {
-                            self.resolve_crate_relative_path(trait_path.span, segments, TypeNS)
-                        } else {
-                            self.resolve_module_relative_path(trait_path.span, segments, TypeNS)
-                        }.map(|binding| binding.span).unwrap_or(syntax_pos::DUMMY_SP)
-                    };
-
-                    if definition_site != syntax_pos::DUMMY_SP {
-                        err.span_label(definition_site,
-                                       &format!("type aliases cannot be used for traits"));
-                    }
+            match path_res.base_def {
+                Def::Trait(_) => {
+                    debug!("(resolving trait) found trait def: {:?}", path_res);
+                    return Ok(path_res);
                 }
-                err.emit();
-                Err(true)
+                Def::Err => return Err(true),
+                _ => {}
             }
+
+            let mut err = resolve_struct_error(self, trait_path.span, {
+                ResolutionError::IsNotATrait(&path_names_to_string(trait_path, path_depth))
+            });
+
+            // If it's a typedef, give a note
+            if let Def::TyAlias(..) = path_res.base_def {
+                err.note(&format!("type aliases cannot be used for traits"));
+            }
+            err.emit();
+            Err(true)
         }).map_err(|error_reported| {
             if error_reported { return }
 
@@ -2274,7 +2253,7 @@
         let resolution = if let Some(resolution) = self.resolve_possibly_assoc_item(pat_id,
                                                                         qself, path, namespace) {
             if resolution.depth == 0 {
-                if expected_fn(resolution.base_def) {
+                if expected_fn(resolution.base_def) || resolution.base_def == Def::Err {
                     resolution
                 } else {
                     resolve_error(
@@ -2345,7 +2324,7 @@
                                 );
                                 None
                             }
-                            Def::Local(..) | Def::Upvar(..) | Def::Fn(..) => {
+                            Def::Local(..) | Def::Upvar(..) | Def::Fn(..) | Def::Err => {
                                 // These entities are explicitly allowed
                                 // to be shadowed by fresh bindings.
                                 None
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index 681d9ec..fc5e2a4 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -73,13 +73,11 @@
 impl<'a> ImportDirective<'a> {
     // Given the binding to which this directive resolves in a particular namespace,
     // this returns the binding for the name this directive defines in that namespace.
-    fn import(&'a self, binding: &'a NameBinding<'a>, privacy_error: Option<Box<PrivacyError<'a>>>)
-              -> NameBinding<'a> {
+    fn import(&'a self, binding: &'a NameBinding<'a>) -> NameBinding<'a> {
         NameBinding {
             kind: NameBindingKind::Import {
                 binding: binding,
                 directive: self,
-                privacy_error: privacy_error,
             },
             span: self.span,
             vis: self.vis,
@@ -328,7 +326,7 @@
     fn define_in_glob_importers(&self, name: Name, ns: Namespace, binding: &'a NameBinding<'a>) {
         if !binding.is_importable() || !binding.is_pseudo_public() { return }
         for &(importer, directive) in self.glob_importers.borrow_mut().iter() {
-            let _ = importer.try_define_child(name, ns, directive.import(binding, None));
+            let _ = importer.try_define_child(name, ns, directive.import(binding));
         }
     }
 }
@@ -409,7 +407,7 @@
                 span: DUMMY_SP,
                 vis: ty::Visibility::Public,
             });
-            let dummy_binding = directive.import(dummy_binding, None);
+            let dummy_binding = directive.import(dummy_binding);
 
             let _ = source_module.try_define_child(target, ValueNS, dummy_binding.clone());
             let _ = source_module.try_define_child(target, TypeNS, dummy_binding);
@@ -494,14 +492,17 @@
             self.resolver.resolve_name_in_module(target_module, source, TypeNS, false, true);
 
         let module_ = self.resolver.current_module;
+        let mut privacy_error = true;
         for &(ns, result, determined) in &[(ValueNS, &value_result, value_determined),
                                            (TypeNS, &type_result, type_determined)] {
-            if determined.get() { continue }
-            if let Indeterminate = *result { continue }
-
-            determined.set(true);
-            if let Success(binding) = *result {
-                if !binding.is_importable() {
+            match *result {
+                Failed(..) if !determined.get() => {
+                    determined.set(true);
+                    module_.update_resolution(target, ns, |resolution| {
+                        resolution.single_imports.directive_failed()
+                    });
+                }
+                Success(binding) if !binding.is_importable() => {
                     let msg = format!("`{}` is not directly importable", target);
                     span_err!(self.resolver.session, directive.span, E0253, "{}", &msg);
                     // Do not import this illegal binding. Import a dummy binding and pretend
@@ -509,23 +510,19 @@
                     self.import_dummy_binding(module_, directive);
                     return Success(());
                 }
-
-                let privacy_error = if !self.resolver.is_accessible(binding.vis) {
-                    Some(Box::new(PrivacyError(directive.span, source, binding)))
-                } else {
-                    None
-                };
-
-                let imported_binding = directive.import(binding, privacy_error);
-                let conflict = module_.try_define_child(target, ns, imported_binding);
-                if let Err(old_binding) = conflict {
-                    let binding = &directive.import(binding, None);
-                    self.resolver.report_conflict(module_, target, ns, binding, old_binding);
+                Success(binding) if !self.resolver.is_accessible(binding.vis) => {}
+                Success(binding) if !determined.get() => {
+                    determined.set(true);
+                    let imported_binding = directive.import(binding);
+                    let conflict = module_.try_define_child(target, ns, imported_binding);
+                    if let Err(old_binding) = conflict {
+                        let binding = &directive.import(binding);
+                        self.resolver.report_conflict(module_, target, ns, binding, old_binding);
+                    }
+                    privacy_error = false;
                 }
-            } else {
-                module_.update_resolution(target, ns, |resolution| {
-                    resolution.single_imports.directive_failed();
-                });
+                Success(_) => privacy_error = false,
+                _ => {}
             }
         }
 
@@ -556,6 +553,14 @@
             _ => (),
         }
 
+        if privacy_error {
+            for &(ns, result) in &[(ValueNS, &value_result), (TypeNS, &type_result)] {
+                let binding = match *result { Success(binding) => binding, _ => continue };
+                self.resolver.privacy_errors.push(PrivacyError(directive.span, source, binding));
+                let _ = module_.try_define_child(target, ns, directive.import(binding));
+            }
+        }
+
         match (&value_result, &type_result) {
             (&Success(binding), _) if !binding.pseudo_vis()
                                               .is_at_least(directive.vis, self.resolver) &&
@@ -592,19 +597,6 @@
             _ => {}
         }
 
-        // Report a privacy error here if all successful namespaces are privacy errors.
-        let mut privacy_error = None;
-        for &ns in &[ValueNS, TypeNS] {
-            privacy_error = match module_.resolve_name(target, ns, true) {
-                Success(&NameBinding {
-                    kind: NameBindingKind::Import { ref privacy_error, .. }, ..
-                }) => privacy_error.as_ref().map(|error| (**error).clone()),
-                _ => continue,
-            };
-            if privacy_error.is_none() { break }
-        }
-        privacy_error.map(|error| self.resolver.privacy_errors.push(error));
-
         // Record what this import resolves to for later uses in documentation,
         // this may resolve to either a value or a type, but for documentation
         // purposes it's good enough to just favor one over the other.
@@ -652,7 +644,7 @@
         }).collect::<Vec<_>>();
         for ((name, ns), binding) in bindings {
             if binding.is_importable() && binding.is_pseudo_public() {
-                let _ = module_.try_define_child(name, ns, directive.import(binding, None));
+                let _ = module_.try_define_child(name, ns, directive.import(binding));
             }
         }
 
diff --git a/src/librustc_trans/_match.rs b/src/librustc_trans/_match.rs
index 08e894f..f7fd970 100644
--- a/src/librustc_trans/_match.rs
+++ b/src/librustc_trans/_match.rs
@@ -190,7 +190,7 @@
 
 use llvm::{ValueRef, BasicBlockRef};
 use rustc_const_eval::check_match::{self, Constructor, StaticInliner};
-use rustc_const_eval::{compare_lit_exprs, eval_const_expr};
+use rustc_const_eval::{compare_lit_exprs, eval_const_expr, fatal_const_eval_err};
 use rustc::hir::def::{Def, DefMap};
 use rustc::hir::def_id::DefId;
 use middle::expr_use_visitor as euv;
@@ -239,9 +239,9 @@
 
 impl<'a> ConstantExpr<'a> {
     fn eq<'b, 'tcx>(self, other: ConstantExpr<'a>, tcx: TyCtxt<'b, 'tcx, 'tcx>) -> bool {
-        match compare_lit_exprs(tcx, self.0, other.0) {
-            Some(result) => result == Ordering::Equal,
-            None => bug!("compare_list_exprs: type mismatch"),
+        match compare_lit_exprs(tcx, self.0.span, self.0, other.0) {
+            Ok(result) => result == Ordering::Equal,
+            Err(_) => bug!("compare_list_exprs: type mismatch"),
         }
     }
 }
@@ -288,7 +288,9 @@
                 let expr = consts::const_expr(ccx, &lit_expr, bcx.fcx.param_substs, None, Yes);
                 let llval = match expr {
                     Ok((llval, _)) => llval,
-                    Err(err) => bcx.ccx().sess().span_fatal(lit_expr.span, &err.description()),
+                    Err(err) => {
+                        fatal_const_eval_err(bcx.tcx(), err.as_inner(), lit_expr.span, "pattern");
+                    }
                 };
                 let lit_datum = immediate_rvalue(llval, lit_ty);
                 let lit_datum = unpack_datum!(bcx, lit_datum.to_appropriate_datum(bcx));
@@ -297,11 +299,11 @@
             ConstantRange(ConstantExpr(ref l1), ConstantExpr(ref l2), _) => {
                 let l1 = match consts::const_expr(ccx, &l1, bcx.fcx.param_substs, None, Yes) {
                     Ok((l1, _)) => l1,
-                    Err(err) => bcx.ccx().sess().span_fatal(l1.span, &err.description()),
+                    Err(err) => fatal_const_eval_err(bcx.tcx(), err.as_inner(), l1.span, "pattern"),
                 };
                 let l2 = match consts::const_expr(ccx, &l2, bcx.fcx.param_substs, None, Yes) {
                     Ok((l2, _)) => l2,
-                    Err(err) => bcx.ccx().sess().span_fatal(l2.span, &err.description()),
+                    Err(err) => fatal_const_eval_err(bcx.tcx(), err.as_inner(), l2.span, "pattern"),
                 };
                 RangeResult(Result::new(bcx, l1), Result::new(bcx, l2))
             }
diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs
index 6c2a09f..587c03a 100644
--- a/src/librustc_trans/abi.rs
+++ b/src/librustc_trans/abi.rs
@@ -552,13 +552,13 @@
     pub fn apply_attrs_llfn(&self, llfn: ValueRef) {
         let mut i = if self.ret.is_indirect() { 1 } else { 0 };
         if !self.ret.is_ignore() {
-            self.ret.attrs.apply_llfn(i, llfn);
+            self.ret.attrs.apply_llfn(llvm::AttributePlace::Argument(i), llfn);
         }
         i += 1;
         for arg in &self.args {
             if !arg.is_ignore() {
                 if arg.pad.is_some() { i += 1; }
-                arg.attrs.apply_llfn(i, llfn);
+                arg.attrs.apply_llfn(llvm::AttributePlace::Argument(i), llfn);
                 i += 1;
             }
         }
@@ -567,13 +567,13 @@
     pub fn apply_attrs_callsite(&self, callsite: ValueRef) {
         let mut i = if self.ret.is_indirect() { 1 } else { 0 };
         if !self.ret.is_ignore() {
-            self.ret.attrs.apply_callsite(i, callsite);
+            self.ret.attrs.apply_callsite(llvm::AttributePlace::Argument(i), callsite);
         }
         i += 1;
         for arg in &self.args {
             if !arg.is_ignore() {
                 if arg.pad.is_some() { i += 1; }
-                arg.attrs.apply_callsite(i, callsite);
+                arg.attrs.apply_callsite(llvm::AttributePlace::Argument(i), callsite);
                 i += 1;
             }
         }
diff --git a/src/librustc_trans/asm.rs b/src/librustc_trans/asm.rs
index e27bec6..5514fb0 100644
--- a/src/librustc_trans/asm.rs
+++ b/src/librustc_trans/asm.rs
@@ -83,8 +83,8 @@
     };
 
     let dialect = match ia.dialect {
-        AsmDialect::Att   => llvm::AD_ATT,
-        AsmDialect::Intel => llvm::AD_Intel
+        AsmDialect::Att   => llvm::AsmDialect::Att,
+        AsmDialect::Intel => llvm::AsmDialect::Intel,
     };
 
     let asm = CString::new(ia.asm.as_bytes()).unwrap();
diff --git a/src/librustc_trans/assert_module_sources.rs b/src/librustc_trans/assert_module_sources.rs
new file mode 100644
index 0000000..e0532e7
--- /dev/null
+++ b/src/librustc_trans/assert_module_sources.rs
@@ -0,0 +1,149 @@
+// Copyright 2012-2015 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.
+
+//! This pass is only used for UNIT TESTS related to incremental
+//! compilation. It tests whether a particular `.o` file will be re-used
+//! from a previous compilation or whether it must be regenerated.
+//!
+//! The user adds annotations to the crate of the following form:
+//!
+//! ```
+//! #![rustc_partition_reused(module="spike", cfg="rpass2")]
+//! #![rustc_partition_translated(module="spike-x", cfg="rpass2")]
+//! ```
+//!
+//! The first indicates (in the cfg `rpass2`) that `spike.o` will be
+//! reused, the second that `spike-x.o` will be recreated. If these
+//! annotations are inaccurate, errors are reported.
+//!
+//! The reason that we use `cfg=...` and not `#[cfg_attr]` is so that
+//! the HIR doesn't change as a result of the annotations, which might
+//! perturb the reuse results.
+
+use rustc::ty::TyCtxt;
+use syntax::ast;
+use syntax::attr::AttrMetaMethods;
+use syntax::parse::token::InternedString;
+
+use {ModuleSource, ModuleTranslation};
+
+const PARTITION_REUSED: &'static str = "rustc_partition_reused";
+const PARTITION_TRANSLATED: &'static str = "rustc_partition_translated";
+
+const MODULE: &'static str = "module";
+const CFG: &'static str = "cfg";
+
+#[derive(Debug, PartialEq)]
+enum Disposition { Reused, Translated }
+
+pub fn assert_module_sources<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                       modules: &[ModuleTranslation]) {
+    let _ignore = tcx.dep_graph.in_ignore();
+
+    if tcx.sess.opts.incremental.is_none() {
+        return;
+    }
+
+    let ams = AssertModuleSource { tcx: tcx, modules: modules };
+    for attr in &tcx.map.krate().attrs {
+        ams.check_attr(attr);
+    }
+}
+
+struct AssertModuleSource<'a, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    modules: &'a [ModuleTranslation],
+}
+
+impl<'a, 'tcx> AssertModuleSource<'a, 'tcx> {
+    fn check_attr(&self, attr: &ast::Attribute) {
+        let disposition = if attr.check_name(PARTITION_REUSED) {
+            Disposition::Reused
+        } else if attr.check_name(PARTITION_TRANSLATED) {
+            Disposition::Translated
+        } else {
+            return;
+        };
+
+        if !self.check_config(attr) {
+            debug!("check_attr: config does not match, ignoring attr");
+            return;
+        }
+
+        let mname = self.field(attr, MODULE);
+        let mtrans = self.modules.iter().find(|mtrans| &mtrans.name[..] == &mname[..]);
+        let mtrans = match mtrans {
+            Some(m) => m,
+            None => {
+                debug!("module name `{}` not found amongst:", mname);
+                for mtrans in self.modules {
+                    debug!("module named `{}` with disposition {:?}",
+                           mtrans.name,
+                           self.disposition(mtrans));
+                }
+
+                self.tcx.sess.span_err(
+                    attr.span,
+                    &format!("no module named `{}`", mname));
+                return;
+            }
+        };
+
+        let mtrans_disposition = self.disposition(mtrans);
+        if disposition != mtrans_disposition {
+            self.tcx.sess.span_err(
+                attr.span,
+                &format!("expected module named `{}` to be {:?} but is {:?}",
+                         mname,
+                         disposition,
+                         mtrans_disposition));
+        }
+    }
+
+    fn disposition(&self, mtrans: &ModuleTranslation) -> Disposition {
+        match mtrans.source {
+            ModuleSource::Preexisting(_) => Disposition::Reused,
+            ModuleSource::Translated(_) => Disposition::Translated,
+        }
+    }
+
+    fn field(&self, attr: &ast::Attribute, name: &str) -> InternedString {
+        for item in attr.meta_item_list().unwrap_or(&[]) {
+            if item.check_name(name) {
+                if let Some(value) = item.value_str() {
+                    return value;
+                } else {
+                    self.tcx.sess.span_fatal(
+                        item.span,
+                        &format!("associated value expected for `{}`", name));
+                }
+            }
+        }
+
+        self.tcx.sess.span_fatal(
+            attr.span,
+            &format!("no field `{}`", name));
+    }
+
+    /// Scan for a `cfg="foo"` attribute and check whether we have a
+    /// cfg flag called `foo`.
+    fn check_config(&self, attr: &ast::Attribute) -> bool {
+        let config = &self.tcx.map.krate().config;
+        let value = self.field(attr, CFG);
+        debug!("check_config(config={:?}, value={:?})", config, value);
+        if config.iter().any(|c| c.check_name(&value[..])) {
+            debug!("check_config: matched");
+            return true;
+        }
+        debug!("check_config: no match found");
+        return false;
+    }
+
+}
diff --git a/src/librustc_trans/attributes.rs b/src/librustc_trans/attributes.rs
index 01e9970..62eac35 100644
--- a/src/librustc_trans/attributes.rs
+++ b/src/librustc_trans/attributes.rs
@@ -9,8 +9,8 @@
 // except according to those terms.
 //! Set and unset common attributes on LLVM values.
 
-use libc::c_uint;
-use llvm::{self, ValueRef};
+use llvm::{self, Attribute, ValueRef};
+use llvm::AttributePlace::Function;
 pub use syntax::attr::InlineAttr;
 use syntax::ast;
 use context::CrateContext;
@@ -20,14 +20,14 @@
 pub fn inline(val: ValueRef, inline: InlineAttr) {
     use self::InlineAttr::*;
     match inline {
-        Hint   => llvm::SetFunctionAttribute(val, llvm::Attribute::InlineHint),
-        Always => llvm::SetFunctionAttribute(val, llvm::Attribute::AlwaysInline),
-        Never  => llvm::SetFunctionAttribute(val, llvm::Attribute::NoInline),
+        Hint   => Attribute::InlineHint.apply_llfn(Function, val),
+        Always => Attribute::AlwaysInline.apply_llfn(Function, val),
+        Never  => Attribute::NoInline.apply_llfn(Function, val),
         None   => {
-            let attr = llvm::Attribute::InlineHint |
-                       llvm::Attribute::AlwaysInline |
-                       llvm::Attribute::NoInline;
-            llvm::RemoveFunctionAttributes(val, attr)
+            let attr = Attribute::InlineHint |
+                       Attribute::AlwaysInline |
+                       Attribute::NoInline;
+            attr.unapply_llfn(Function, val)
         },
     };
 }
@@ -35,56 +35,37 @@
 /// Tell LLVM to emit or not emit the information necessary to unwind the stack for the function.
 #[inline]
 pub fn emit_uwtable(val: ValueRef, emit: bool) {
-    if emit {
-        llvm::SetFunctionAttribute(val, llvm::Attribute::UWTable);
-    } else {
-        llvm::RemoveFunctionAttributes(val, llvm::Attribute::UWTable);
-    }
+    Attribute::UWTable.toggle_llfn(Function, val, emit);
 }
 
 /// Tell LLVM whether the function can or cannot unwind.
 #[inline]
 pub fn unwind(val: ValueRef, can_unwind: bool) {
-    if can_unwind {
-        llvm::RemoveFunctionAttributes(val, llvm::Attribute::NoUnwind);
-    } else {
-        llvm::SetFunctionAttribute(val, llvm::Attribute::NoUnwind);
-    }
+    Attribute::NoUnwind.toggle_llfn(Function, val, !can_unwind);
 }
 
 /// Tell LLVM whether it should optimise function for size.
 #[inline]
 #[allow(dead_code)] // possibly useful function
 pub fn set_optimize_for_size(val: ValueRef, optimize: bool) {
-    if optimize {
-        llvm::SetFunctionAttribute(val, llvm::Attribute::OptimizeForSize);
-    } else {
-        llvm::RemoveFunctionAttributes(val, llvm::Attribute::OptimizeForSize);
-    }
+    Attribute::OptimizeForSize.toggle_llfn(Function, val, optimize);
 }
 
 /// Tell LLVM if this function should be 'naked', i.e. skip the epilogue and prologue.
 #[inline]
 pub fn naked(val: ValueRef, is_naked: bool) {
-    if is_naked {
-        llvm::SetFunctionAttribute(val, llvm::Attribute::Naked);
-    } else {
-        llvm::RemoveFunctionAttributes(val, llvm::Attribute::Naked);
-    }
+    Attribute::Naked.toggle_llfn(Function, val, is_naked);
 }
 
 pub fn set_frame_pointer_elimination(ccx: &CrateContext, llfn: ValueRef) {
     // FIXME: #11906: Omitting frame pointers breaks retrieving the value of a
     // parameter.
     if ccx.sess().must_not_eliminate_frame_pointers() {
-        unsafe {
-            let attr = "no-frame-pointer-elim\0".as_ptr() as *const _;
-            let val = "true\0".as_ptr() as *const _;
-            llvm::LLVMAddFunctionAttrStringValue(llfn,
-                                                 llvm::FunctionIndex as c_uint,
-                                                 attr,
-                                                 val);
-        }
+        llvm::AddFunctionAttrStringValue(
+            llfn,
+            llvm::AttributePlace::Function,
+            "no-frame-pointer-elim\0",
+            "true\0")
     }
 }
 
@@ -98,13 +79,12 @@
 
     for attr in attrs {
         if attr.check_name("cold") {
-            llvm::Attributes::default().set(llvm::Attribute::Cold)
-                .apply_llfn(llvm::FunctionIndex as usize, llfn)
+            Attribute::Cold.apply_llfn(Function, llfn);
         } else if attr.check_name("naked") {
             naked(llfn, true);
         } else if attr.check_name("allocator") {
-            llvm::Attributes::default().set(llvm::Attribute::NoAlias)
-                .apply_llfn(llvm::ReturnIndex as usize, llfn)
+            Attribute::NoAlias.apply_llfn(
+                llvm::AttributePlace::ReturnValue(), llfn);
         } else if attr.check_name("unwind") {
             unwind(llfn, true);
         }
diff --git a/src/librustc_trans/back/archive.rs b/src/librustc_trans/back/archive.rs
index 29019f3..e063209 100644
--- a/src/librustc_trans/back/archive.rs
+++ b/src/librustc_trans/back/archive.rs
@@ -293,7 +293,7 @@
                                                members.as_ptr(),
                                                self.should_update_symbols,
                                                kind);
-            let ret = if r != 0 {
+            let ret = if r.into_result().is_err() {
                 let err = llvm::LLVMRustGetLastError();
                 let msg = if err.is_null() {
                     "failed to write archive".to_string()
diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs
index 33cffa8..8ce2fa7 100644
--- a/src/librustc_trans/back/write.rs
+++ b/src/librustc_trans/back/write.rs
@@ -10,18 +10,21 @@
 
 use back::lto;
 use back::link::{get_linker, remove};
+use rustc_incremental::save_trans_partition;
 use session::config::{OutputFilenames, Passes, SomePasses, AllPasses};
 use session::Session;
 use session::config::{self, OutputType};
 use llvm;
 use llvm::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef, ContextRef};
 use llvm::SMDiagnosticRef;
-use {CrateTranslation, ModuleTranslation};
+use {CrateTranslation, ModuleLlvm, ModuleSource, ModuleTranslation};
 use util::common::time;
 use util::common::path2cstr;
+use util::fs::link_or_copy;
 use errors::{self, Handler, Level, DiagnosticBuilder};
 use errors::emitter::Emitter;
 use syntax_pos::MultiSpan;
+use context::{is_pie_binary, get_reloc_model};
 
 use std::collections::HashMap;
 use std::ffi::{CStr, CString};
@@ -51,7 +54,7 @@
         let output_c = path2cstr(output);
         let result = llvm::LLVMRustWriteOutputFile(
                 target, pm, m, output_c.as_ptr(), file_type);
-        if !result {
+        if result.into_result().is_err() {
             llvm_err(handler, format!("could not write output to {}", output.display()));
         }
     }
@@ -135,11 +138,11 @@
 
 fn get_llvm_opt_level(optimize: config::OptLevel) -> llvm::CodeGenOptLevel {
     match optimize {
-      config::OptLevel::No => llvm::CodeGenLevelNone,
-      config::OptLevel::Less => llvm::CodeGenLevelLess,
-      config::OptLevel::Default => llvm::CodeGenLevelDefault,
-      config::OptLevel::Aggressive => llvm::CodeGenLevelAggressive,
-      _ => llvm::CodeGenLevelDefault,
+      config::OptLevel::No => llvm::CodeGenOptLevel::None,
+      config::OptLevel::Less => llvm::CodeGenOptLevel::Less,
+      config::OptLevel::Default => llvm::CodeGenOptLevel::Default,
+      config::OptLevel::Aggressive => llvm::CodeGenOptLevel::Aggressive,
+      _ => llvm::CodeGenOptLevel::Default,
     }
 }
 
@@ -152,32 +155,11 @@
 }
 
 pub fn create_target_machine(sess: &Session) -> TargetMachineRef {
-    let reloc_model_arg = match sess.opts.cg.relocation_model {
-        Some(ref s) => &s[..],
-        None => &sess.target.target.options.relocation_model[..],
-    };
-    let reloc_model = match reloc_model_arg {
-        "pic" => llvm::RelocPIC,
-        "static" => llvm::RelocStatic,
-        "default" => llvm::RelocDefault,
-        "dynamic-no-pic" => llvm::RelocDynamicNoPic,
-        _ => {
-            sess.err(&format!("{:?} is not a valid relocation mode",
-                             sess.opts
-                                 .cg
-                                 .relocation_model));
-            sess.abort_if_errors();
-            bug!();
-        }
-    };
+    let reloc_model = get_reloc_model(sess);
 
     let opt_level = get_llvm_opt_level(sess.opts.optimize);
     let use_softfp = sess.opts.cg.soft_float;
 
-    let any_library = sess.crate_types.borrow().iter().any(|ty| {
-        *ty != config::CrateTypeExecutable
-    });
-
     let ffunction_sections = sess.target.target.options.function_sections;
     let fdata_sections = ffunction_sections;
 
@@ -187,11 +169,11 @@
     };
 
     let code_model = match code_model_arg {
-        "default" => llvm::CodeModelDefault,
-        "small" => llvm::CodeModelSmall,
-        "kernel" => llvm::CodeModelKernel,
-        "medium" => llvm::CodeModelMedium,
-        "large" => llvm::CodeModelLarge,
+        "default" => llvm::CodeModel::Default,
+        "small" => llvm::CodeModel::Small,
+        "kernel" => llvm::CodeModel::Kernel,
+        "medium" => llvm::CodeModel::Medium,
+        "large" => llvm::CodeModel::Large,
         _ => {
             sess.err(&format!("{:?} is not a valid code model",
                              sess.opts
@@ -218,7 +200,7 @@
             reloc_model,
             opt_level,
             use_softfp,
-            !any_library && reloc_model == llvm::RelocPIC,
+            is_pie_binary(sess),
             ffunction_sections,
             fdata_sections,
         )
@@ -335,6 +317,8 @@
     remark: Passes,
     // Worker thread number
     worker: usize,
+    // Directory where incremental data is stored (if any)
+    incremental: Option<PathBuf>,
 }
 
 impl<'a> CodegenContext<'a> {
@@ -345,6 +329,7 @@
             plugin_passes: sess.plugin_llvm_passes.borrow().clone(),
             remark: sess.opts.cg.remark.clone(),
             worker: 0,
+            incremental: sess.opts.incremental.clone(),
         }
     }
 }
@@ -380,7 +365,7 @@
                                         cookie: c_uint) {
     let HandlerFreeVars { cgcx, .. } = *(user as *const HandlerFreeVars);
 
-    let msg = llvm::build_string(|s| llvm::LLVMWriteSMDiagnosticToString(diag, s))
+    let msg = llvm::build_string(|s| llvm::LLVMRustWriteSMDiagnosticToString(diag, s))
         .expect("non-UTF8 SMDiagnostic");
 
     report_inline_asm(cgcx, &msg[..], cookie);
@@ -422,10 +407,11 @@
 // Unsafe due to LLVM calls.
 unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
                                mtrans: ModuleTranslation,
+                               mllvm: ModuleLlvm,
                                config: ModuleConfig,
                                output_names: OutputFilenames) {
-    let llmod = mtrans.llmod;
-    let llcx = mtrans.llcx;
+    let llmod = mllvm.llmod;
+    let llcx = mllvm.llcx;
     let tm = config.tm;
 
     // llcx doesn't outlive this function, so we can put this on the stack.
@@ -435,7 +421,7 @@
     };
     let fv = &fv as *const HandlerFreeVars as *mut c_void;
 
-    llvm::LLVMSetInlineAsmDiagnosticHandler(llcx, inline_asm_handler, fv);
+    llvm::LLVMRustSetInlineAsmDiagnosticHandler(llcx, inline_asm_handler, fv);
     llvm::LLVMContextSetDiagnosticHandler(llcx, diagnostic_handler, fv);
 
     let module_name = Some(&mtrans.name[..]);
@@ -463,9 +449,9 @@
                 return false;
             }
             let pass_manager = match llvm::LLVMRustPassKind(pass) {
-                llvm::SupportedPassKind::Function => fpm,
-                llvm::SupportedPassKind::Module => mpm,
-                llvm::SupportedPassKind::Unsupported => {
+                llvm::PassKind::Function => fpm,
+                llvm::PassKind::Module => mpm,
+                llvm::PassKind::Other => {
                     cgcx.handler.err("Encountered LLVM pass kind we can't handle");
                     return true
                 },
@@ -593,7 +579,7 @@
             };
             with_codegen(tm, llmod, config.no_builtins, |cpm| {
                 write_output_file(cgcx.handler, tm, cpm, llmod, &path,
-                                  llvm::AssemblyFileType);
+                                  llvm::FileType::AssemblyFile);
             });
             if config.emit_obj {
                 llvm::LLVMDisposeModule(llmod);
@@ -602,14 +588,15 @@
 
         if write_obj {
             with_codegen(tm, llmod, config.no_builtins, |cpm| {
-                write_output_file(cgcx.handler, tm, cpm, llmod, &obj_out, llvm::ObjectFileType);
+                write_output_file(cgcx.handler, tm, cpm, llmod, &obj_out,
+                                  llvm::FileType::ObjectFile);
             });
         }
     });
 
     if copy_bc_to_obj {
         debug!("copying bitcode {:?} to obj {:?}", bc_out, obj_out);
-        if let Err(e) = fs::copy(&bc_out, &obj_out) {
+        if let Err(e) = link_or_copy(&bc_out, &obj_out) {
             cgcx.handler.err(&format!("failed to copy bitcode to object file: {}", e));
         }
     }
@@ -628,8 +615,14 @@
 pub fn cleanup_llvm(trans: &CrateTranslation) {
     for module in trans.modules.iter() {
         unsafe {
-            llvm::LLVMDisposeModule(module.llmod);
-            llvm::LLVMContextDispose(module.llcx);
+            match module.source {
+                ModuleSource::Translated(llvm) => {
+                    llvm::LLVMDisposeModule(llvm.llmod);
+                    llvm::LLVMContextDispose(llvm.llcx);
+                }
+                ModuleSource::Preexisting(_) => {
+                }
+            }
         }
     }
 }
@@ -743,6 +736,23 @@
         run_work_multithreaded(sess, work_items, num_workers);
     }
 
+    // If in incr. comp. mode, preserve the `.o` files for potential re-use
+    for mtrans in trans.modules.iter() {
+        let mut files = vec![];
+
+        if modules_config.emit_obj {
+            let path = crate_output.temp_path(OutputType::Object, Some(&mtrans.name));
+            files.push((OutputType::Object, path));
+        }
+
+        if modules_config.emit_bc {
+            let path = crate_output.temp_path(OutputType::Bitcode, Some(&mtrans.name));
+            files.push((OutputType::Bitcode, path));
+        }
+
+        save_trans_partition(sess, &mtrans.name, mtrans.symbol_name_hash, &files);
+    }
+
     // All codegen is finished.
     unsafe {
         llvm::LLVMRustDisposeTargetMachine(tm);
@@ -916,10 +926,37 @@
 fn execute_work_item(cgcx: &CodegenContext,
                      work_item: WorkItem) {
     unsafe {
-        optimize_and_codegen(cgcx,
-                             work_item.mtrans,
-                             work_item.config,
-                             work_item.output_names);
+        match work_item.mtrans.source {
+            ModuleSource::Translated(mllvm) => {
+                debug!("llvm-optimizing {:?}", work_item.mtrans.name);
+                optimize_and_codegen(cgcx,
+                                     work_item.mtrans,
+                                     mllvm,
+                                     work_item.config,
+                                     work_item.output_names);
+            }
+            ModuleSource::Preexisting(wp) => {
+                let incremental = cgcx.incremental.as_ref().unwrap();
+                let name = &work_item.mtrans.name;
+                for (kind, saved_file) in wp.saved_files {
+                    let obj_out = work_item.output_names.temp_path(kind, Some(name));
+                    let source_file = incremental.join(&saved_file);
+                    debug!("copying pre-existing module `{}` from {:?} to {}",
+                           work_item.mtrans.name,
+                           source_file,
+                           obj_out.display());
+                    match link_or_copy(&source_file, &obj_out) {
+                        Ok(()) => { }
+                        Err(err) => {
+                            cgcx.handler.err(&format!("unable to copy {} to {}: {}",
+                                                      source_file.display(),
+                                                      obj_out.display(),
+                                                      err));
+                        }
+                    }
+                }
+            }
+        }
     }
 }
 
@@ -955,6 +992,8 @@
         let mut tx = Some(tx);
         futures.push(rx);
 
+        let incremental = sess.opts.incremental.clone();
+
         thread::Builder::new().name(format!("codegen-{}", i)).spawn(move || {
             let diag_handler = Handler::with_emitter(true, false, box diag_emitter);
 
@@ -966,6 +1005,7 @@
                 plugin_passes: plugin_passes,
                 remark: remark,
                 worker: i,
+                incremental: incremental,
             };
 
             loop {
@@ -1039,7 +1079,7 @@
     // reasonable defaults and prepare it to actually populate the pass
     // manager.
     let builder = llvm::LLVMPassManagerBuilderCreate();
-    let opt_level = config.opt_level.unwrap_or(llvm::CodeGenLevelNone);
+    let opt_level = config.opt_level.unwrap_or(llvm::CodeGenOptLevel::None);
     let opt_size = config.opt_size.unwrap_or(llvm::CodeGenOptSizeNone);
     let inline_threshold = config.inline_threshold;
 
@@ -1063,7 +1103,7 @@
         (_, _, Some(t)) => {
             llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, t as u32);
         }
-        (llvm::CodeGenLevelAggressive, _, _) => {
+        (llvm::CodeGenOptLevel::Aggressive, _, _) => {
             llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 275);
         }
         (_, llvm::CodeGenOptSizeDefault, _) => {
@@ -1072,15 +1112,18 @@
         (_, llvm::CodeGenOptSizeAggressive, _) => {
             llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 25);
         }
-        (llvm::CodeGenLevelNone, _, _) => {
+        (llvm::CodeGenOptLevel::None, _, _) => {
             llvm::LLVMRustAddAlwaysInlinePass(builder, false);
         }
-        (llvm::CodeGenLevelLess, _, _) => {
+        (llvm::CodeGenOptLevel::Less, _, _) => {
             llvm::LLVMRustAddAlwaysInlinePass(builder, true);
         }
-        (llvm::CodeGenLevelDefault, _, _) => {
+        (llvm::CodeGenOptLevel::Default, _, _) => {
             llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 225);
         }
+        (llvm::CodeGenOptLevel::Other, _, _) => {
+            bug!("CodeGenOptLevel::Other selected")
+        }
     }
 
     f(builder);
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index ea8c248..1077cb2 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -26,8 +26,11 @@
 #![allow(non_camel_case_types)]
 
 use super::CrateTranslation;
+use super::ModuleLlvm;
+use super::ModuleSource;
 use super::ModuleTranslation;
 
+use assert_module_sources;
 use back::link;
 use back::linker::LinkerInfo;
 use llvm::{BasicBlockRef, Linkage, ValueRef, Vector, get_param};
@@ -40,7 +43,7 @@
 use rustc::traits;
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc::ty::adjustment::CustomCoerceUnsized;
-use rustc::dep_graph::DepNode;
+use rustc::dep_graph::{DepNode, WorkProduct};
 use rustc::hir::map as hir_map;
 use rustc::util::common::time;
 use rustc::mir::mir_map::MirMap;
@@ -1915,9 +1918,9 @@
 }
 
 pub fn trans_instance<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, instance: Instance<'tcx>) {
-    let instance = inline::maybe_inline_instance(ccx, instance);
+    let local_instance = inline::maybe_inline_instance(ccx, instance);
 
-    let fn_node_id = ccx.tcx().map.as_local_node_id(instance.def).unwrap();
+    let fn_node_id = ccx.tcx().map.as_local_node_id(local_instance.def).unwrap();
 
     let _s = StatRecorder::new(ccx, ccx.tcx().node_path_str(fn_node_id));
     debug!("trans_instance(instance={:?})", instance);
@@ -1933,7 +1936,7 @@
     let sig = ccx.tcx().normalize_associated_type(&sig);
     let abi = fn_ty.fn_abi();
 
-    let lldecl = match ccx.instances().borrow().get(&instance) {
+    let lldecl = match ccx.instances().borrow().get(&local_instance) {
         Some(&val) => val,
         None => bug!("Instance `{:?}` not already declared", instance)
     };
@@ -2133,7 +2136,7 @@
 
     let instance = Instance::mono(ccx.shared(), main_def_id);
 
-    if !ccx.codegen_unit().items.contains_key(&TransItem::Fn(instance)) {
+    if !ccx.codegen_unit().contains_item(&TransItem::Fn(instance)) {
         // We want to create the wrapper in the same codegen unit as Rust's main
         // function.
         return;
@@ -2257,12 +2260,20 @@
 
 /// Find any symbols that are defined in one compilation unit, but not declared
 /// in any other compilation unit.  Give these symbols internal linkage.
-fn internalize_symbols<'a, 'tcx>(ccxs: &CrateContextList<'a, 'tcx>,
+fn internalize_symbols<'a, 'tcx>(sess: &Session,
+                                 ccxs: &CrateContextList<'a, 'tcx>,
                                  symbol_map: &SymbolMap<'tcx>,
                                  reachable: &FnvHashSet<&str>) {
     let scx = ccxs.shared();
     let tcx = scx.tcx();
 
+    // In incr. comp. mode, we can't necessarily see all refs since we
+    // don't generate LLVM IR for reused modules, so skip this
+    // step. Later we should get smarter.
+    if sess.opts.debugging_opts.incremental.is_some() {
+        return;
+    }
+
     // 'unsafe' because we are holding on to CStr's from the LLVM module within
     // this block.
     unsafe {
@@ -2270,7 +2281,7 @@
 
         // Collect all symbols that need to stay externally visible because they
         // are referenced via a declaration in some other codegen unit.
-        for ccx in ccxs.iter() {
+        for ccx in ccxs.iter_need_trans() {
             for val in iter_globals(ccx.llmod()).chain(iter_functions(ccx.llmod())) {
                 let linkage = llvm::LLVMGetLinkage(val);
                 // We only care about external declarations (not definitions)
@@ -2315,7 +2326,7 @@
         // Examine each external definition.  If the definition is not used in
         // any other compilation unit, and is not reachable from other crates,
         // then give it internal linkage.
-        for ccx in ccxs.iter() {
+        for ccx in ccxs.iter_need_trans() {
             for val in iter_globals(ccx.llmod()).chain(iter_functions(ccx.llmod())) {
                 let linkage = llvm::LLVMGetLinkage(val);
 
@@ -2336,8 +2347,9 @@
                     let has_fixed_linkage = linkage_fixed_explicitly.contains(&name_cow);
 
                     if !is_referenced_somewhere && !is_reachable && !has_fixed_linkage {
-                        llvm::SetLinkage(val, llvm::InternalLinkage);
-                        llvm::SetDLLStorageClass(val, llvm::DefaultStorageClass);
+                        llvm::LLVMSetLinkage(val, llvm::InternalLinkage);
+                        llvm::LLVMSetDLLStorageClass(val,
+                                                     llvm::DLLStorageClass::Default);
                         llvm::UnsetComdat(val);
                     }
                 }
@@ -2362,7 +2374,7 @@
         "\x01__imp_"
     };
     unsafe {
-        for ccx in cx.iter() {
+        for ccx in cx.iter_need_trans() {
             let exported: Vec<_> = iter_globals(ccx.llmod())
                                        .filter(|&val| {
                                            llvm::LLVMGetLinkage(val) ==
@@ -2382,7 +2394,7 @@
                                               imp_name.as_ptr() as *const _);
                 let init = llvm::LLVMConstBitCast(val, i8p_ty.to_ref());
                 llvm::LLVMSetInitializer(imp, init);
-                llvm::SetLinkage(imp, llvm::ExternalLinkage);
+                llvm::LLVMSetLinkage(imp, llvm::ExternalLinkage);
             }
         }
     }
@@ -2514,8 +2526,11 @@
 
     let metadata_module = ModuleTranslation {
         name: "metadata".to_string(),
-        llcx: shared_ccx.metadata_llcx(),
-        llmod: shared_ccx.metadata_llmod(),
+        symbol_name_hash: 0, // we always rebuild metadata, at least for now
+        source: ModuleSource::Translated(ModuleLlvm {
+            llcx: shared_ccx.metadata_llcx(),
+            llmod: shared_ccx.metadata_llmod(),
+        }),
     };
     let no_builtins = attr::contains_name(&krate.attrs, "no_builtins");
 
@@ -2525,17 +2540,34 @@
 
     let symbol_map = Rc::new(symbol_map);
 
+    let previous_work_products = trans_reuse_previous_work_products(tcx,
+                                                                    &codegen_units,
+                                                                    &symbol_map);
+
     let crate_context_list = CrateContextList::new(&shared_ccx,
                                                    codegen_units,
+                                                   previous_work_products,
                                                    symbol_map.clone());
-    let modules = crate_context_list.iter()
-        .map(|ccx| ModuleTranslation {
-            name: String::from(&ccx.codegen_unit().name[..]),
-            llcx: ccx.llcx(),
-            llmod: ccx.llmod()
+    let modules: Vec<_> = crate_context_list.iter_all()
+        .map(|ccx| {
+            let source = match ccx.previous_work_product() {
+                Some(buf) => ModuleSource::Preexisting(buf.clone()),
+                None => ModuleSource::Translated(ModuleLlvm {
+                    llcx: ccx.llcx(),
+                    llmod: ccx.llmod(),
+                }),
+            };
+
+            ModuleTranslation {
+                name: String::from(ccx.codegen_unit().name()),
+                symbol_name_hash: ccx.codegen_unit().compute_symbol_name_hash(tcx, &symbol_map),
+                source: source,
+            }
         })
         .collect();
 
+    assert_module_sources::assert_module_sources(tcx, &modules);
+
     // Skip crate items and just output metadata in -Z no-trans mode.
     if tcx.sess.opts.no_trans {
         let linker_info = LinkerInfo::new(&shared_ccx, &[]);
@@ -2551,41 +2583,44 @@
     }
 
     // Instantiate translation items without filling out definitions yet...
-    for ccx in crate_context_list.iter() {
-        let trans_items = ccx.codegen_unit()
-                             .items_in_deterministic_order(tcx, &symbol_map);
+    for ccx in crate_context_list.iter_need_trans() {
+        let cgu = ccx.codegen_unit();
+        let trans_items = cgu.items_in_deterministic_order(tcx, &symbol_map);
 
-        for (trans_item, linkage) in trans_items {
-            trans_item.predefine(&ccx, linkage);
-        }
+        tcx.dep_graph.with_task(cgu.work_product_dep_node(), || {
+            for (trans_item, linkage) in trans_items {
+                trans_item.predefine(&ccx, linkage);
+            }
+        });
     }
 
     // ... and now that we have everything pre-defined, fill out those definitions.
-    for ccx in crate_context_list.iter() {
-        let trans_items = ccx.codegen_unit()
-                             .items_in_deterministic_order(tcx, &symbol_map);
-
-        for (trans_item, _) in trans_items {
-           trans_item.define(&ccx);
-        }
-
-        // If this codegen unit contains the main function, also create the
-        // wrapper here
-        maybe_create_entry_wrapper(&ccx);
-
-        // Run replace-all-uses-with for statics that need it
-        for &(old_g, new_g) in ccx.statics_to_rauw().borrow().iter() {
-            unsafe {
-                let bitcast = llvm::LLVMConstPointerCast(new_g, llvm::LLVMTypeOf(old_g));
-                llvm::LLVMReplaceAllUsesWith(old_g, bitcast);
-                llvm::LLVMDeleteGlobal(old_g);
+    for ccx in crate_context_list.iter_need_trans() {
+        let cgu = ccx.codegen_unit();
+        let trans_items = cgu.items_in_deterministic_order(tcx, &symbol_map);
+        tcx.dep_graph.with_task(cgu.work_product_dep_node(), || {
+            for (trans_item, _) in trans_items {
+                trans_item.define(&ccx);
             }
-        }
 
-        // Finalize debuginfo
-        if ccx.sess().opts.debuginfo != NoDebugInfo {
-            debuginfo::finalize(&ccx);
-        }
+            // If this codegen unit contains the main function, also create the
+            // wrapper here
+            maybe_create_entry_wrapper(&ccx);
+
+            // Run replace-all-uses-with for statics that need it
+            for &(old_g, new_g) in ccx.statics_to_rauw().borrow().iter() {
+                unsafe {
+                    let bitcast = llvm::LLVMConstPointerCast(new_g, llvm::LLVMTypeOf(old_g));
+                    llvm::LLVMReplaceAllUsesWith(old_g, bitcast);
+                    llvm::LLVMDeleteGlobal(old_g);
+                }
+            }
+
+            // Finalize debuginfo
+            if ccx.sess().opts.debuginfo != NoDebugInfo {
+                debuginfo::finalize(&ccx);
+            }
+        });
     }
 
     symbol_names_test::report_symbol_names(&shared_ccx);
@@ -2654,7 +2689,8 @@
     }
 
     time(shared_ccx.sess().time_passes(), "internalize symbols", || {
-        internalize_symbols(&crate_context_list,
+        internalize_symbols(sess,
+                            &crate_context_list,
                             &symbol_map,
                             &reachable_symbols.iter()
                                               .map(|s| &s[..])
@@ -2679,6 +2715,38 @@
     }
 }
 
+/// For each CGU, identify if we can reuse an existing object file (or
+/// maybe other context).
+fn trans_reuse_previous_work_products(tcx: TyCtxt,
+                                      codegen_units: &[CodegenUnit],
+                                      symbol_map: &SymbolMap)
+                                      -> Vec<Option<WorkProduct>> {
+    debug!("trans_reuse_previous_work_products()");
+    codegen_units
+        .iter()
+        .map(|cgu| {
+            let id = cgu.work_product_id();
+
+            let hash = cgu.compute_symbol_name_hash(tcx, symbol_map);
+
+            debug!("trans_reuse_previous_work_products: id={:?} hash={}", id, hash);
+
+            if let Some(work_product) = tcx.dep_graph.previous_work_product(&id) {
+                if work_product.input_hash == hash {
+                    debug!("trans_reuse_previous_work_products: reusing {:?}", work_product);
+                    return Some(work_product);
+                } else {
+                    debug!("trans_reuse_previous_work_products: \
+                            not reusing {:?} because hash changed to {:?}",
+                           work_product, hash);
+                }
+            }
+
+            None
+        })
+        .collect()
+}
+
 fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>)
                                                      -> (Vec<CodegenUnit<'tcx>>, SymbolMap<'tcx>) {
     let time_passes = scx.sess().time_passes();
@@ -2739,10 +2807,10 @@
         let mut item_to_cgus = HashMap::new();
 
         for cgu in &codegen_units {
-            for (&trans_item, &linkage) in &cgu.items {
+            for (&trans_item, &linkage) in cgu.items() {
                 item_to_cgus.entry(trans_item)
                             .or_insert(Vec::new())
-                            .push((cgu.name.clone(), linkage));
+                            .push((cgu.name().clone(), linkage));
             }
         }
 
diff --git a/src/librustc_trans/build.rs b/src/librustc_trans/build.rs
index 4a7a573..8cd47bd 100644
--- a/src/librustc_trans/build.rs
+++ b/src/librustc_trans/build.rs
@@ -12,7 +12,7 @@
 #![allow(non_snake_case)]
 
 use llvm;
-use llvm::{AtomicBinOp, AtomicOrdering, SynchronizationScope, AsmDialect};
+use llvm::{AtomicRmwBinOp, AtomicOrdering, SynchronizationScope, AsmDialect};
 use llvm::{Opcode, IntPredicate, RealPredicate};
 use llvm::{ValueRef, BasicBlockRef};
 use common::*;
@@ -1117,7 +1117,7 @@
                      weak: llvm::Bool) -> ValueRef {
     B(cx).atomic_cmpxchg(dst, cmp, src, order, failure_order, weak)
 }
-pub fn AtomicRMW(cx: Block, op: AtomicBinOp,
+pub fn AtomicRMW(cx: Block, op: AtomicRmwBinOp,
                  dst: ValueRef, src: ValueRef,
                  order: AtomicOrdering) -> ValueRef {
     B(cx).atomic_rmw(op, dst, src, order)
diff --git a/src/librustc_trans/builder.rs b/src/librustc_trans/builder.rs
index e88257d..90f96af 100644
--- a/src/librustc_trans/builder.rs
+++ b/src/librustc_trans/builder.rs
@@ -11,7 +11,7 @@
 #![allow(dead_code)] // FFI wrappers
 
 use llvm;
-use llvm::{AtomicBinOp, AtomicOrdering, SynchronizationScope, AsmDialect};
+use llvm::{AtomicRmwBinOp, AtomicOrdering, SynchronizationScope, AsmDialect};
 use llvm::{Opcode, IntPredicate, RealPredicate, False, OperandBundleDef};
 use llvm::{ValueRef, BasicBlockRef, BuilderRef, ModuleRef};
 use base;
@@ -503,8 +503,8 @@
         unsafe {
             let ty = Type::from_ref(llvm::LLVMTypeOf(ptr));
             let align = llalign_of_pref(self.ccx, ty.element_type());
-            llvm::LLVMBuildAtomicLoad(self.llbuilder, ptr, noname(), order,
-                                      align as c_uint)
+            llvm::LLVMRustBuildAtomicLoad(self.llbuilder, ptr, noname(), order,
+                                          align as c_uint)
         }
     }
 
@@ -565,7 +565,7 @@
         unsafe {
             let ty = Type::from_ref(llvm::LLVMTypeOf(ptr));
             let align = llalign_of_pref(self.ccx, ty.element_type());
-            llvm::LLVMBuildAtomicStore(self.llbuilder, val, ptr, order, align as c_uint);
+            llvm::LLVMRustBuildAtomicStore(self.llbuilder, val, ptr, order, align as c_uint);
         }
     }
 
@@ -840,8 +840,8 @@
         debug!("Asm Output Type: {:?}", output);
         let fty = Type::func(&argtys[..], &output);
         unsafe {
-            let v = llvm::LLVMInlineAsm(
-                fty.to_ref(), asm, cons, volatile, alignstack, dia as c_uint);
+            let v = llvm::LLVMRustInlineAsm(
+                fty.to_ref(), asm, cons, volatile, alignstack, dia);
             self.call(v, inputs, None)
         }
     }
@@ -1083,11 +1083,11 @@
                          failure_order: AtomicOrdering,
                          weak: llvm::Bool) -> ValueRef {
         unsafe {
-            llvm::LLVMBuildAtomicCmpXchg(self.llbuilder, dst, cmp, src,
+            llvm::LLVMRustBuildAtomicCmpXchg(self.llbuilder, dst, cmp, src,
                                          order, failure_order, weak)
         }
     }
-    pub fn atomic_rmw(&self, op: AtomicBinOp,
+    pub fn atomic_rmw(&self, op: AtomicRmwBinOp,
                      dst: ValueRef, src: ValueRef,
                      order: AtomicOrdering) -> ValueRef {
         unsafe {
@@ -1097,7 +1097,7 @@
 
     pub fn atomic_fence(&self, order: AtomicOrdering, scope: SynchronizationScope) {
         unsafe {
-            llvm::LLVMBuildAtomicFence(self.llbuilder, order, scope);
+            llvm::LLVMRustBuildAtomicFence(self.llbuilder, order, scope);
         }
     }
 }
diff --git a/src/librustc_trans/closure.rs b/src/librustc_trans/closure.rs
index 90443d9..e53a5ed 100644
--- a/src/librustc_trans/closure.rs
+++ b/src/librustc_trans/closure.rs
@@ -181,6 +181,41 @@
     llfn
 }
 
+fn translating_closure_body_via_mir_will_fail(ccx: &CrateContext,
+                                              closure_def_id: DefId)
+                                              -> bool {
+    let default_to_mir = ccx.sess().opts.debugging_opts.orbit;
+    let invert = if default_to_mir { "rustc_no_mir" } else { "rustc_mir" };
+    let use_mir = default_to_mir ^ ccx.tcx().has_attr(closure_def_id, invert);
+
+    !use_mir
+}
+
+pub fn trans_closure_body_via_mir<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+                                            closure_def_id: DefId,
+                                            closure_substs: ty::ClosureSubsts<'tcx>) {
+    use syntax::ast::DUMMY_NODE_ID;
+    use syntax_pos::DUMMY_SP;
+    use syntax::ptr::P;
+
+    trans_closure_expr(Dest::Ignore(ccx),
+                       &hir::FnDecl {
+                           inputs: P::new(),
+                           output: hir::NoReturn(DUMMY_SP),
+                           variadic: false
+                       },
+                       &hir::Block {
+                           stmts: P::new(),
+                           expr: None,
+                           id: DUMMY_NODE_ID,
+                           rules: hir::DefaultBlock,
+                           span: DUMMY_SP
+                       },
+                       DUMMY_NODE_ID,
+                       closure_def_id,
+                       closure_substs);
+}
+
 pub enum Dest<'a, 'tcx: 'a> {
     SaveIn(Block<'a, 'tcx>, ValueRef),
     Ignore(&'a CrateContext<'a, 'tcx>)
@@ -213,8 +248,15 @@
     // If we have not done so yet, translate this closure's body
     if  !ccx.instances().borrow().contains_key(&instance) {
         let llfn = get_or_create_closure_declaration(ccx, closure_def_id, closure_substs);
-        llvm::SetLinkage(llfn, llvm::WeakODRLinkage);
-        llvm::SetUniqueComdat(ccx.llmod(), llfn);
+
+        unsafe {
+            if ccx.sess().target.target.options.allows_weak_linkage {
+                llvm::LLVMSetLinkage(llfn, llvm::WeakODRLinkage);
+                llvm::SetUniqueComdat(ccx.llmod(), llfn);
+            } else {
+                llvm::LLVMSetLinkage(llfn, llvm::InternalLinkage);
+            }
+        }
 
         // set an inline hint for all closures
         attributes::inline(llfn, attributes::InlineAttr::Hint);
@@ -296,6 +338,39 @@
     // If this is a closure, redirect to it.
     let llfn = get_or_create_closure_declaration(ccx, closure_def_id, substs);
 
+    // If weak linkage is not allowed, we have to make sure that a local,
+    // private copy of the closure is available in this codegen unit
+    if !ccx.sess().target.target.options.allows_weak_linkage &&
+       !ccx.sess().opts.single_codegen_unit() {
+
+        if let Some(node_id) = ccx.tcx().map.as_local_node_id(closure_def_id) {
+            // If the closure is defined in the local crate, we can always just
+            // translate it.
+            let (decl, body) = match ccx.tcx().map.expect_expr(node_id).node {
+                hir::ExprClosure(_, ref decl, ref body, _) => (decl, body),
+                _ => { unreachable!() }
+            };
+
+            trans_closure_expr(Dest::Ignore(ccx),
+                               decl,
+                               body,
+                               node_id,
+                               closure_def_id,
+                               substs);
+        } else {
+            // If the closure is defined in an upstream crate, we can only
+            // translate it if MIR-trans is active.
+
+            if translating_closure_body_via_mir_will_fail(ccx, closure_def_id) {
+                ccx.sess().fatal("You have run into a known limitation of the \
+                                  MingW toolchain. Either compile with -Zorbit or \
+                                  with -Ccodegen-units=1 to work around it.");
+            }
+
+            trans_closure_body_via_mir(ccx, closure_def_id, substs);
+        }
+    }
+
     // If the closure is a Fn closure, but a FnOnce is needed (etc),
     // then adapt the self type
     let llfn_closure_kind = ccx.tcx().closure_kind(closure_def_id);
diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs
index d057f62..a1783e9 100644
--- a/src/librustc_trans/common.rs
+++ b/src/librustc_trans/common.rs
@@ -980,7 +980,7 @@
         });
         llvm::LLVMSetInitializer(g, sc);
         llvm::LLVMSetGlobalConstant(g, True);
-        llvm::SetLinkage(g, llvm::InternalLinkage);
+        llvm::LLVMSetLinkage(g, llvm::InternalLinkage);
 
         cx.const_cstr_cache().borrow_mut().insert(s, g);
         g
@@ -1235,7 +1235,6 @@
                                      inlined_vid: ast::NodeId)
                                      -> ty::VariantDef<'tcx>
 {
-
     let ctor_ty = ccx.tcx().node_id_to_type(inlined_vid);
     debug!("inlined_variant_def: ctor_ty={:?} inlined_vid={:?}", ctor_ty,
            inlined_vid);
@@ -1245,13 +1244,18 @@
         }), ..}) => ty,
         _ => ctor_ty
     }.ty_adt_def().unwrap();
-    let inlined_vid_def_id = ccx.tcx().map.local_def_id(inlined_vid);
-    adt_def.variants.iter().find(|v| {
-        inlined_vid_def_id == v.did ||
-            ccx.external().borrow().get(&v.did) == Some(&Some(inlined_vid))
-    }).unwrap_or_else(|| {
-        bug!("no variant for {:?}::{}", adt_def, inlined_vid)
-    })
+    let variant_def_id = if ccx.tcx().map.is_inlined(inlined_vid) {
+        ccx.defid_for_inlined_node(inlined_vid).unwrap()
+    } else {
+        ccx.tcx().map.local_def_id(inlined_vid)
+    };
+
+    adt_def.variants
+           .iter()
+           .find(|v| variant_def_id == v.did)
+           .unwrap_or_else(|| {
+                bug!("no variant for {:?}::{}", adt_def, inlined_vid)
+            })
 }
 
 // To avoid UB from LLVM, these two functions mask RHS with an
diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs
index 00feb2c..7afb525 100644
--- a/src/librustc_trans/consts.rs
+++ b/src/librustc_trans/consts.rs
@@ -10,11 +10,11 @@
 
 
 use llvm;
-use llvm::{ConstFCmp, ConstICmp, SetLinkage, SetUnnamedAddr};
+use llvm::{SetUnnamedAddr};
 use llvm::{InternalLinkage, ValueRef, Bool, True};
 use middle::const_qualif::ConstQualif;
 use rustc_const_eval::{ConstEvalErr, lookup_const_fn_by_id, lookup_const_by_id, ErrKind};
-use rustc_const_eval::eval_repeat_count;
+use rustc_const_eval::{eval_length, report_const_eval_err, note_const_eval_err};
 use rustc::hir::def::Def;
 use rustc::hir::def_id::DefId;
 use rustc::hir::map as hir_map;
@@ -44,7 +44,6 @@
 use rustc::hir;
 
 use std::ffi::{CStr, CString};
-use std::borrow::Cow;
 use libc::c_uint;
 use syntax::ast::{self, LitKind};
 use syntax::attr::{self, AttrMetaMethods};
@@ -126,7 +125,7 @@
         });
         llvm::LLVMSetInitializer(gv, cv);
         llvm::LLVMSetAlignment(gv, align);
-        SetLinkage(gv, InternalLinkage);
+        llvm::LLVMSetLinkage(gv, InternalLinkage);
         SetUnnamedAddr(gv, true);
         gv
     }
@@ -250,10 +249,11 @@
             Compiletime(e) => e,
         }
     }
-    pub fn description(&self) -> Cow<str> {
+
+    pub fn as_inner(&self) -> &ConstEvalErr {
         match self {
-            &Runtime(ref e) => e.description(),
-            &Compiletime(ref e) => e.description(),
+            &Runtime(ref e) => e,
+            &Compiletime(ref e) => e,
         }
     }
 }
@@ -274,7 +274,7 @@
     let empty_substs = ccx.tcx().mk_substs(Substs::empty());
     match get_const_expr_as_global(ccx, expr, ConstQualif::empty(), empty_substs, TrueConst::Yes) {
         Err(Runtime(err)) => {
-            ccx.tcx().sess.span_err(expr.span, &err.description());
+            report_const_eval_err(ccx.tcx(), &err, expr.span, "expression").emit();
             Err(Compiletime(err))
         },
         other => other,
@@ -526,12 +526,15 @@
         (Ok(x), _) => Ok(x),
         (Err(err), TrueConst::Yes) => {
             let err = ConstEvalErr{ span: span, kind: err };
-            cx.tcx().sess.span_err(span, &err.description());
+            report_const_eval_err(cx.tcx(), &err, span, "expression").emit();
             Err(Compiletime(err))
         },
         (Err(err), TrueConst::No) => {
             let err = ConstEvalErr{ span: span, kind: err };
-            cx.tcx().sess.span_warn(span, &err.description());
+            let mut diag = cx.tcx().sess.struct_span_warn(
+                span, "this expression will panic at run-time");
+            note_const_eval_err(cx.tcx(), &err, span, "expression", &mut diag);
+            diag.emit();
             Err(Runtime(err))
         },
     }
@@ -634,10 +637,10 @@
                 hir::BiEq | hir::BiNe | hir::BiLt | hir::BiLe | hir::BiGt | hir::BiGe => {
                     if is_float {
                         let cmp = base::bin_op_to_fcmp_predicate(b.node);
-                        ConstFCmp(cmp, te1, te2)
+                        llvm::LLVMConstFCmp(cmp, te1, te2)
                     } else {
                         let cmp = base::bin_op_to_icmp_predicate(b.node, signed);
-                        ConstICmp(cmp, te1, te2)
+                        llvm::LLVMConstICmp(cmp, te1, te2)
                     }
                 },
             } } // unsafe { match b.node {
@@ -875,7 +878,7 @@
         hir::ExprRepeat(ref elem, ref count) => {
             let unit_ty = ety.sequence_element_type(cx.tcx());
             let llunitty = type_of::type_of(cx, unit_ty);
-            let n = eval_repeat_count(cx.tcx(), count);
+            let n = eval_length(cx.tcx(), count, "repeat count").unwrap();
             let unit_val = const_expr(cx, &elem, param_substs, fn_args, trueconst)?.0;
             let vs = vec![unit_val; n];
             if val_ty(unit_val) != llunitty {
@@ -1023,10 +1026,10 @@
                              .get(TransItem::Static(id))
                              .expect("Local statics should always be in the SymbolMap");
                 // Make sure that this is never executed for something inlined.
-                assert!(!ccx.external_srcs().borrow().contains_key(&id));
+                assert!(!ccx.tcx().map.is_inlined(id));
 
                 let defined_in_current_codegen_unit = ccx.codegen_unit()
-                                                         .items
+                                                         .items()
                                                          .contains_key(&TransItem::Static(id));
                 if defined_in_current_codegen_unit {
                     if declare::get_declared_value(ccx, sym).is_none() {
@@ -1069,7 +1072,7 @@
                     unsafe {
                         // Declare a symbol `foo` with the desired linkage.
                         let g1 = declare::declare_global(ccx, &sym, llty2);
-                        llvm::SetLinkage(g1, linkage);
+                        llvm::LLVMSetLinkage(g1, linkage);
 
                         // Declare an internal global `extern_with_linkage_foo` which
                         // is initialized with the address of `foo`.  If `foo` is
@@ -1083,7 +1086,7 @@
                             ccx.sess().span_fatal(span,
                                 &format!("symbol `{}` is already defined", &sym))
                         });
-                        llvm::SetLinkage(g2, llvm::InternalLinkage);
+                        llvm::LLVMSetLinkage(g2, llvm::InternalLinkage);
                         llvm::LLVMSetInitializer(g2, g1);
                         g2
                     }
@@ -1123,7 +1126,9 @@
             }
         }
         if ccx.use_dll_storage_attrs() {
-            llvm::SetDLLStorageClass(g, llvm::DLLImportStorageClass);
+            unsafe {
+                llvm::LLVMSetDLLStorageClass(g, llvm::DLLStorageClass::DllImport);
+            }
         }
         g
     };
@@ -1179,7 +1184,7 @@
             let name_str_ref = CStr::from_ptr(llvm::LLVMGetValueName(datum.val));
             let name_string = CString::new(name_str_ref.to_bytes()).unwrap();
             llvm::LLVMSetValueName(datum.val, empty_string.as_ptr());
-            let new_g = llvm::LLVMGetOrInsertGlobal(
+            let new_g = llvm::LLVMRustGetOrInsertGlobal(
                 ccx.llmod(), name_string.as_ptr(), val_llty.to_ref());
             // To avoid breaking any invariants, we leave around the old
             // global for the moment; we'll replace all references to it
diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs
index 8890372..166ce99 100644
--- a/src/librustc_trans/context.rs
+++ b/src/librustc_trans/context.rs
@@ -10,7 +10,7 @@
 
 use llvm;
 use llvm::{ContextRef, ModuleRef, ValueRef, BuilderRef};
-use rustc::dep_graph::{DepNode, DepTrackingMap, DepTrackingMapConfig};
+use rustc::dep_graph::{DepNode, DepTrackingMap, DepTrackingMapConfig, WorkProduct};
 use middle::cstore::LinkMeta;
 use rustc::hir::def::ExportMap;
 use rustc::hir::def_id::DefId;
@@ -34,9 +34,10 @@
 use rustc::ty::{self, Ty, TyCtxt};
 use session::config::NoDebugInfo;
 use session::Session;
+use session::config;
 use symbol_map::SymbolMap;
 use util::sha2::Sha256;
-use util::nodemap::{NodeMap, NodeSet, DefIdMap, FnvHashMap, FnvHashSet};
+use util::nodemap::{NodeSet, DefIdMap, FnvHashMap, FnvHashSet};
 
 use std::ffi::{CStr, CString};
 use std::cell::{Cell, RefCell};
@@ -95,16 +96,12 @@
 pub struct LocalCrateContext<'tcx> {
     llmod: ModuleRef,
     llcx: ContextRef,
+    previous_work_product: Option<WorkProduct>,
     tn: TypeNames, // FIXME: This seems to be largely unused.
     codegen_unit: CodegenUnit<'tcx>,
     needs_unwind_cleanup_cache: RefCell<FnvHashMap<Ty<'tcx>, bool>>,
     fn_pointer_shims: RefCell<FnvHashMap<Ty<'tcx>, ValueRef>>,
     drop_glues: RefCell<FnvHashMap<DropGlueKind<'tcx>, (ValueRef, FnType)>>,
-    /// Track mapping of external ids to local items imported for inlining
-    external: RefCell<DefIdMap<Option<ast::NodeId>>>,
-    /// Backwards version of the `external` map (inlined items to where they
-    /// came from)
-    external_srcs: RefCell<NodeMap<DefId>>,
     /// Cache instances of monomorphic and polymorphic items
     instances: RefCell<FnvHashMap<Instance<'tcx>, ValueRef>>,
     monomorphizing: RefCell<DefIdMap<usize>>,
@@ -198,24 +195,39 @@
 }
 
 impl<'a, 'tcx: 'a> CrateContextList<'a, 'tcx> {
-
     pub fn new(shared_ccx: &'a SharedCrateContext<'a, 'tcx>,
                codegen_units: Vec<CodegenUnit<'tcx>>,
+               previous_work_products: Vec<Option<WorkProduct>>,
                symbol_map: Rc<SymbolMap<'tcx>>)
                -> CrateContextList<'a, 'tcx> {
         CrateContextList {
             shared: shared_ccx,
-            local_ccxs: codegen_units.into_iter().map(|codegen_unit| {
-                LocalCrateContext::new(shared_ccx, codegen_unit, symbol_map.clone())
+            local_ccxs: codegen_units.into_iter().zip(previous_work_products).map(|(cgu, wp)| {
+                LocalCrateContext::new(shared_ccx, cgu, wp, symbol_map.clone())
             }).collect()
         }
     }
 
-    pub fn iter<'b>(&'b self) -> CrateContextIterator<'b, 'tcx> {
+    /// Iterate over all crate contexts, whether or not they need
+    /// translation.  That is, whether or not a `.o` file is available
+    /// for re-use from a previous incr. comp.).
+    pub fn iter_all<'b>(&'b self) -> CrateContextIterator<'b, 'tcx> {
         CrateContextIterator {
             shared: self.shared,
             index: 0,
-            local_ccxs: &self.local_ccxs[..]
+            local_ccxs: &self.local_ccxs[..],
+            filter_to_previous_work_product_unavail: false,
+        }
+    }
+
+    /// Iterator over all CCX that need translation (cannot reuse results from
+    /// previous incr. comp.).
+    pub fn iter_need_trans<'b>(&'b self) -> CrateContextIterator<'b, 'tcx> {
+        CrateContextIterator {
+            shared: self.shared,
+            index: 0,
+            local_ccxs: &self.local_ccxs[..],
+            filter_to_previous_work_product_unavail: true,
         }
     }
 
@@ -239,24 +251,38 @@
     shared: &'a SharedCrateContext<'a, 'tcx>,
     local_ccxs: &'a [LocalCrateContext<'tcx>],
     index: usize,
+
+    /// if true, only return results where `previous_work_product` is none
+    filter_to_previous_work_product_unavail: bool,
 }
 
 impl<'a, 'tcx> Iterator for CrateContextIterator<'a,'tcx> {
     type Item = CrateContext<'a, 'tcx>;
 
     fn next(&mut self) -> Option<CrateContext<'a, 'tcx>> {
-        if self.index >= self.local_ccxs.len() {
-            return None;
+        loop {
+            if self.index >= self.local_ccxs.len() {
+                return None;
+            }
+
+            let index = self.index;
+            self.index += 1;
+
+            let ccx = CrateContext {
+                shared: self.shared,
+                index: index,
+                local_ccxs: self.local_ccxs,
+            };
+
+            if
+                self.filter_to_previous_work_product_unavail &&
+                ccx.previous_work_product().is_some()
+            {
+                continue;
+            }
+
+            return Some(ccx);
         }
-
-        let index = self.index;
-        self.index += 1;
-
-        Some(CrateContext {
-            shared: self.shared,
-            index: index,
-            local_ccxs: self.local_ccxs,
-        })
     }
 }
 
@@ -292,6 +318,38 @@
     }
 }
 
+pub fn get_reloc_model(sess: &Session) -> llvm::RelocMode {
+    let reloc_model_arg = match sess.opts.cg.relocation_model {
+        Some(ref s) => &s[..],
+        None => &sess.target.target.options.relocation_model[..],
+    };
+
+    match reloc_model_arg {
+        "pic" => llvm::RelocMode::PIC,
+        "static" => llvm::RelocMode::Static,
+        "default" => llvm::RelocMode::Default,
+        "dynamic-no-pic" => llvm::RelocMode::DynamicNoPic,
+        _ => {
+            sess.err(&format!("{:?} is not a valid relocation mode",
+                             sess.opts
+                                 .cg
+                                 .relocation_model));
+            sess.abort_if_errors();
+            bug!();
+        }
+    }
+}
+
+fn is_any_library(sess: &Session) -> bool {
+    sess.crate_types.borrow().iter().any(|ty| {
+        *ty != config::CrateTypeExecutable
+    })
+}
+
+pub fn is_pie_binary(sess: &Session) -> bool {
+    !is_any_library(sess) && get_reloc_model(sess) == llvm::RelocMode::PIC
+}
+
 unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextRef, ModuleRef) {
     let llcx = llvm::LLVMContextCreate();
     let mod_name = CString::new(mod_name).unwrap();
@@ -307,7 +365,25 @@
         let data_layout = str::from_utf8(CStr::from_ptr(data_layout).to_bytes())
             .ok().expect("got a non-UTF8 data-layout from LLVM");
 
-        if sess.target.target.data_layout != data_layout {
+        // Unfortunately LLVM target specs change over time, and right now we
+        // don't have proper support to work with any more than one
+        // `data_layout` than the one that is in the rust-lang/rust repo. If
+        // this compiler is configured against a custom LLVM, we may have a
+        // differing data layout, even though we should update our own to use
+        // that one.
+        //
+        // As an interim hack, if CFG_LLVM_ROOT is not an empty string then we
+        // disable this check entirely as we may be configured with something
+        // that has a different target layout.
+        //
+        // Unsure if this will actually cause breakage when rustc is configured
+        // as such.
+        //
+        // FIXME(#34960)
+        let cfg_llvm_root = option_env!("CFG_LLVM_ROOT").unwrap_or("");
+        let custom_llvm_used = cfg_llvm_root.trim() != "";
+
+        if !custom_llvm_used && sess.target.target.data_layout != data_layout {
             bug!("data-layout for builtin `{}` target, `{}`, \
                   differs from LLVM default, `{}`",
                  sess.target.target.llvm_target,
@@ -322,6 +398,11 @@
     let llvm_target = sess.target.target.llvm_target.as_bytes();
     let llvm_target = CString::new(llvm_target).unwrap();
     llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr());
+
+    if is_pie_binary(sess) {
+        llvm::LLVMRustSetModulePIELevel(llmod);
+    }
+
     (llcx, llmod)
 }
 
@@ -510,6 +591,7 @@
 impl<'tcx> LocalCrateContext<'tcx> {
     fn new<'a>(shared: &SharedCrateContext<'a, 'tcx>,
                codegen_unit: CodegenUnit<'tcx>,
+               previous_work_product: Option<WorkProduct>,
                symbol_map: Rc<SymbolMap<'tcx>>)
            -> LocalCrateContext<'tcx> {
         unsafe {
@@ -521,13 +603,15 @@
             // crashes if the module identifier is same as other symbols
             // such as a function name in the module.
             // 1. http://llvm.org/bugs/show_bug.cgi?id=11479
-            let llmod_id = format!("{}.rs", codegen_unit.name);
+            let llmod_id = format!("{}.rs", codegen_unit.name());
 
             let (llcx, llmod) = create_context_and_module(&shared.tcx.sess,
                                                           &llmod_id[..]);
 
             let dbg_cx = if shared.tcx.sess.opts.debuginfo != NoDebugInfo {
-                Some(debuginfo::CrateDebugContext::new(llmod))
+                let dctx = debuginfo::CrateDebugContext::new(llmod);
+                debuginfo::metadata::compile_unit_metadata(shared, &dctx, shared.tcx.sess);
+                Some(dctx)
             } else {
                 None
             };
@@ -535,13 +619,12 @@
             let local_ccx = LocalCrateContext {
                 llmod: llmod,
                 llcx: llcx,
+                previous_work_product: previous_work_product,
                 codegen_unit: codegen_unit,
                 tn: TypeNames::new(),
                 needs_unwind_cleanup_cache: RefCell::new(FnvHashMap()),
                 fn_pointer_shims: RefCell::new(FnvHashMap()),
                 drop_glues: RefCell::new(FnvHashMap()),
-                external: RefCell::new(DefIdMap()),
-                external_srcs: RefCell::new(NodeMap()),
                 instances: RefCell::new(FnvHashMap()),
                 monomorphizing: RefCell::new(DefIdMap()),
                 vtables: RefCell::new(FnvHashMap()),
@@ -694,6 +777,10 @@
         self.local().llcx
     }
 
+    pub fn previous_work_product(&self) -> Option<&WorkProduct> {
+        self.local().previous_work_product.as_ref()
+    }
+
     pub fn codegen_unit(&self) -> &CodegenUnit<'tcx> {
         &self.local().codegen_unit
     }
@@ -731,12 +818,12 @@
         &self.local().drop_glues
     }
 
-    pub fn external<'a>(&'a self) -> &'a RefCell<DefIdMap<Option<ast::NodeId>>> {
-        &self.local().external
+    pub fn local_node_for_inlined_defid<'a>(&'a self, def_id: DefId) -> Option<ast::NodeId> {
+        self.sess().cstore.local_node_for_inlined_defid(def_id)
     }
 
-    pub fn external_srcs<'a>(&'a self) -> &'a RefCell<NodeMap<DefId>> {
-        &self.local().external_srcs
+    pub fn defid_for_inlined_node<'a>(&'a self, node_id: ast::NodeId) -> Option<DefId> {
+        self.sess().cstore.defid_for_inlined_node(node_id)
     }
 
     pub fn instances<'a>(&'a self) -> &'a RefCell<FnvHashMap<Instance<'tcx>, ValueRef>> {
diff --git a/src/librustc_trans/debuginfo/create_scope_map.rs b/src/librustc_trans/debuginfo/create_scope_map.rs
index 0b75402..fe6a48d 100644
--- a/src/librustc_trans/debuginfo/create_scope_map.rs
+++ b/src/librustc_trans/debuginfo/create_scope_map.rs
@@ -133,7 +133,7 @@
     let loc = span_start(ccx, scope_data.span);
     scopes[scope] = unsafe {
     let file_metadata = file_metadata(ccx, &loc.file.name, &loc.file.abs_path);
-        llvm::LLVMDIBuilderCreateLexicalBlock(
+        llvm::LLVMRustDIBuilderCreateLexicalBlock(
             DIB(ccx),
             parent_scope,
             file_metadata,
@@ -156,7 +156,7 @@
     let parent_scope = scope_stack.last().unwrap().scope_metadata;
 
     let scope_metadata = unsafe {
-        llvm::LLVMDIBuilderCreateLexicalBlock(
+        llvm::LLVMRustDIBuilderCreateLexicalBlock(
             DIB(cx),
             parent_scope,
             file_metadata,
@@ -272,7 +272,7 @@
                 let parent_scope = scope_stack.last().unwrap().scope_metadata;
 
                 let scope_metadata = unsafe {
-                    llvm::LLVMDIBuilderCreateLexicalBlock(
+                    llvm::LLVMRustDIBuilderCreateLexicalBlock(
                         DIB(cx),
                         parent_scope,
                         file_metadata,
diff --git a/src/librustc_trans/debuginfo/gdb.rs b/src/librustc_trans/debuginfo/gdb.rs
index cf31285..0a8d490 100644
--- a/src/librustc_trans/debuginfo/gdb.rs
+++ b/src/librustc_trans/debuginfo/gdb.rs
@@ -77,7 +77,7 @@
             llvm::LLVMSetInitializer(section_var, C_bytes(ccx, section_contents));
             llvm::LLVMSetGlobalConstant(section_var, llvm::True);
             llvm::LLVMSetUnnamedAddr(section_var, llvm::True);
-            llvm::SetLinkage(section_var, llvm::Linkage::LinkOnceODRLinkage);
+            llvm::LLVMSetLinkage(section_var, llvm::Linkage::LinkOnceODRLinkage);
             // This should make sure that the whole section is not larger than
             // the string it contains. Otherwise we get a warning from GDB.
             llvm::LLVMSetAlignment(section_var, 1);
diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs
index 46813d9..8011347 100644
--- a/src/librustc_trans/debuginfo/metadata.rs
+++ b/src/librustc_trans/debuginfo/metadata.rs
@@ -18,7 +18,9 @@
                    fn_should_be_ignored, is_node_local_to_unit};
 use super::namespace::mangled_name_of_item;
 use super::type_names::{compute_debuginfo_type_name, push_debuginfo_type_name};
-use super::{declare_local, VariableKind, VariableAccess};
+use super::{declare_local, VariableKind, VariableAccess, CrateDebugContext};
+use context::SharedCrateContext;
+use session::Session;
 
 use llvm::{self, ValueRef};
 use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor, DICompositeType};
@@ -48,7 +50,6 @@
 use syntax::parse::token;
 use syntax_pos::{self, Span};
 
-
 // From DWARF 5.
 // See http://www.dwarfstd.org/ShowIssue.php?issue=140129.1
 const DW_LANG_RUST: c_uint = 0x1c;
@@ -67,7 +68,6 @@
 pub const UNKNOWN_COLUMN_NUMBER: c_uint = 0;
 
 // ptr::null() doesn't work :(
-pub const NO_FILE_METADATA: DIFile = (0 as DIFile);
 pub const NO_SCOPE_METADATA: DIScope = (0 as DIScope);
 
 const FLAGS_NONE: c_uint = 0;
@@ -326,13 +326,12 @@
             // First, find out the 'real' def_id of the type. Items inlined from
             // other crates have to be mapped back to their source.
             let def_id = if let Some(node_id) = cx.tcx().map.as_local_node_id(def_id) {
-                match cx.external_srcs().borrow().get(&node_id).cloned() {
-                    Some(source_def_id) => {
-                        // The given def_id identifies the inlined copy of a
-                        // type definition, let's take the source of the copy.
-                        source_def_id
-                    }
-                    None => def_id
+                if cx.tcx().map.is_inlined(node_id) {
+                    // The given def_id identifies the inlined copy of a
+                    // type definition, let's take the source of the copy.
+                    cx.defid_for_inlined_node(node_id).unwrap()
+                } else {
+                    def_id
                 }
             } else {
                 def_id
@@ -505,12 +504,12 @@
     };
 
     let subrange = unsafe {
-        llvm::LLVMDIBuilderGetOrCreateSubrange(DIB(cx), 0, upper_bound)
+        llvm::LLVMRustDIBuilderGetOrCreateSubrange(DIB(cx), 0, upper_bound)
     };
 
     let subscripts = create_DIArray(DIB(cx), &[subrange]);
     let metadata = unsafe {
-        llvm::LLVMDIBuilderCreateArrayType(
+        llvm::LLVMRustDIBuilderCreateArrayType(
             DIB(cx),
             bytes_to_bits(array_size_in_bytes),
             bytes_to_bits(element_type_align),
@@ -613,9 +612,9 @@
 
     return MetadataCreationResult::new(
         unsafe {
-            llvm::LLVMDIBuilderCreateSubroutineType(
+            llvm::LLVMRustDIBuilderCreateSubroutineType(
                 DIB(cx),
-                NO_FILE_METADATA,
+                unknown_file_metadata(cx),
                 create_DIArray(DIB(cx), &signature_metadata[..]))
         },
         false);
@@ -652,6 +651,7 @@
     let (containing_scope, _) = get_namespace_and_span_for_item(cx, def_id);
 
     let trait_llvm_type = type_of::type_of(cx, trait_object_type);
+    let file_metadata = unknown_file_metadata(cx);
 
     composite_type_metadata(cx,
                             trait_llvm_type,
@@ -659,7 +659,7 @@
                             unique_type_id,
                             &[],
                             containing_scope,
-                            NO_FILE_METADATA,
+                            file_metadata,
                             syntax_pos::DUMMY_SP)
 }
 
@@ -885,8 +885,8 @@
     let file_name = CString::new(file_name).unwrap();
     let work_dir = CString::new(work_dir).unwrap();
     let file_metadata = unsafe {
-        llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name.as_ptr(),
-                                      work_dir.as_ptr())
+        llvm::LLVMRustDIBuilderCreateFile(DIB(cx), file_name.as_ptr(),
+                                          work_dir.as_ptr())
     };
 
     let mut created_files = debug_context(cx).created_files.borrow_mut();
@@ -916,7 +916,7 @@
 
 pub fn diverging_type_metadata(cx: &CrateContext) -> DIType {
     unsafe {
-        llvm::LLVMDIBuilderCreateBasicType(
+        llvm::LLVMRustDIBuilderCreateBasicType(
             DIB(cx),
             "!\0".as_ptr() as *const _,
             bytes_to_bits(0),
@@ -951,7 +951,7 @@
     let (size, align) = size_and_align_of(cx, llvm_type);
     let name = CString::new(name).unwrap();
     let ty_metadata = unsafe {
-        llvm::LLVMDIBuilderCreateBasicType(
+        llvm::LLVMRustDIBuilderCreateBasicType(
             DIB(cx),
             name.as_ptr(),
             bytes_to_bits(size),
@@ -971,7 +971,7 @@
     let name = compute_debuginfo_type_name(cx, pointer_type, false);
     let name = CString::new(name).unwrap();
     let ptr_metadata = unsafe {
-        llvm::LLVMDIBuilderCreatePointerType(
+        llvm::LLVMRustDIBuilderCreatePointerType(
             DIB(cx),
             pointee_type_metadata,
             bytes_to_bits(pointer_size),
@@ -981,14 +981,17 @@
     return ptr_metadata;
 }
 
-pub fn compile_unit_metadata(cx: &CrateContext) -> DIDescriptor {
-    let work_dir = &cx.sess().working_dir;
-    let compile_unit_name = match cx.sess().local_crate_source_file {
-        None => fallback_path(cx),
+pub fn compile_unit_metadata(scc: &SharedCrateContext,
+                             debug_context: &CrateDebugContext,
+                             sess: &Session)
+                             -> DIDescriptor {
+    let work_dir = &sess.working_dir;
+    let compile_unit_name = match sess.local_crate_source_file {
+        None => fallback_path(scc),
         Some(ref abs_path) => {
             if abs_path.is_relative() {
-                cx.sess().warn("debuginfo: Invalid path to crate's local root source file!");
-                fallback_path(cx)
+                sess.warn("debuginfo: Invalid path to crate's local root source file!");
+                fallback_path(scc)
             } else {
                 match abs_path.strip_prefix(work_dir) {
                     Ok(ref p) if p.is_relative() => {
@@ -998,7 +1001,7 @@
                             path2cstr(&Path::new(".").join(p))
                         }
                     }
-                    _ => fallback_path(cx)
+                    _ => fallback_path(scc)
                 }
             }
         }
@@ -1014,20 +1017,20 @@
     let flags = "\0";
     let split_name = "\0";
     return unsafe {
-        llvm::LLVMDIBuilderCreateCompileUnit(
-            debug_context(cx).builder,
+        llvm::LLVMRustDIBuilderCreateCompileUnit(
+            debug_context.builder,
             DW_LANG_RUST,
             compile_unit_name,
             work_dir.as_ptr(),
             producer.as_ptr(),
-            cx.sess().opts.optimize != config::OptLevel::No,
+            sess.opts.optimize != config::OptLevel::No,
             flags.as_ptr() as *const _,
             0,
             split_name.as_ptr() as *const _)
     };
 
-    fn fallback_path(cx: &CrateContext) -> CString {
-        CString::new(cx.link_meta().crate_name.clone()).unwrap()
+    fn fallback_path(scc: &SharedCrateContext) -> CString {
+        CString::new(scc.link_meta().crate_name.clone()).unwrap()
     }
 }
 
@@ -1593,7 +1596,7 @@
             let token = v.name.as_str();
             let name = CString::new(token.as_bytes()).unwrap();
             unsafe {
-                llvm::LLVMDIBuilderCreateEnumerator(
+                llvm::LLVMRustDIBuilderCreateEnumerator(
                     DIB(cx),
                     name.as_ptr(),
                     v.disr_val.to_u64_unchecked())
@@ -1620,11 +1623,11 @@
 
                 let name = CString::new(discriminant_name.as_bytes()).unwrap();
                 let discriminant_type_metadata = unsafe {
-                    llvm::LLVMDIBuilderCreateEnumerationType(
+                    llvm::LLVMRustDIBuilderCreateEnumerationType(
                         DIB(cx),
                         containing_scope,
                         name.as_ptr(),
-                        NO_FILE_METADATA,
+                        file_metadata,
                         UNKNOWN_LINE_NUMBER,
                         bytes_to_bits(discriminant_size),
                         bytes_to_bits(discriminant_align),
@@ -1664,7 +1667,7 @@
     let enum_name = CString::new(enum_name).unwrap();
     let unique_type_id_str = CString::new(unique_type_id_str.as_bytes()).unwrap();
     let enum_metadata = unsafe {
-        llvm::LLVMDIBuilderCreateUnionType(
+        llvm::LLVMRustDIBuilderCreateUnionType(
         DIB(cx),
         containing_scope,
         enum_name.as_ptr(),
@@ -1766,11 +1769,11 @@
             let member_name = member_description.name.as_bytes();
             let member_name = CString::new(member_name).unwrap();
             unsafe {
-                llvm::LLVMDIBuilderCreateMemberType(
+                llvm::LLVMRustDIBuilderCreateMemberType(
                     DIB(cx),
                     composite_type_metadata,
                     member_name.as_ptr(),
-                    NO_FILE_METADATA,
+                    unknown_file_metadata(cx),
                     UNKNOWN_LINE_NUMBER,
                     bytes_to_bits(member_size),
                     bytes_to_bits(member_align),
@@ -1783,13 +1786,14 @@
 
     unsafe {
         let type_array = create_DIArray(DIB(cx), &member_metadata[..]);
-        llvm::LLVMDICompositeTypeSetTypeArray(DIB(cx), composite_type_metadata, type_array);
+        llvm::LLVMRustDICompositeTypeSetTypeArray(
+            DIB(cx), composite_type_metadata, type_array);
     }
 }
 
-// A convenience wrapper around LLVMDIBuilderCreateStructType(). Does not do any
-// caching, does not add any fields to the struct. This can be done later with
-// set_members_of_composite_type().
+// A convenience wrapper around LLVMRustDIBuilderCreateStructType(). Does not do
+// any caching, does not add any fields to the struct. This can be done later
+// with set_members_of_composite_type().
 fn create_struct_stub(cx: &CrateContext,
                       struct_llvm_type: Type,
                       struct_type_name: &str,
@@ -1804,16 +1808,16 @@
     let name = CString::new(struct_type_name).unwrap();
     let unique_type_id = CString::new(unique_type_id_str.as_bytes()).unwrap();
     let metadata_stub = unsafe {
-        // LLVMDIBuilderCreateStructType() wants an empty array. A null
+        // LLVMRustDIBuilderCreateStructType() wants an empty array. A null
         // pointer will lead to hard to trace and debug LLVM assertions
         // later on in llvm/lib/IR/Value.cpp.
         let empty_array = create_DIArray(DIB(cx), &[]);
 
-        llvm::LLVMDIBuilderCreateStructType(
+        llvm::LLVMRustDIBuilderCreateStructType(
             DIB(cx),
             containing_scope,
             name.as_ptr(),
-            NO_FILE_METADATA,
+            unknown_file_metadata(cx),
             UNKNOWN_LINE_NUMBER,
             bytes_to_bits(struct_size),
             bytes_to_bits(struct_align),
@@ -1842,7 +1846,7 @@
     // crate should already contain debuginfo for it. More importantly, the
     // global might not even exist in un-inlined form anywhere which would lead
     // to a linker errors.
-    if cx.external_srcs().borrow().contains_key(&node_id) {
+    if cx.tcx().map.is_inlined(node_id) {
         return;
     }
 
@@ -1853,7 +1857,7 @@
         let loc = span_start(cx, span);
         (file_metadata(cx, &loc.file.name, &loc.file.abs_path), loc.line as c_uint)
     } else {
-        (NO_FILE_METADATA, UNKNOWN_LINE_NUMBER)
+        (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER)
     };
 
     let is_local_to_unit = is_node_local_to_unit(cx, node_id);
@@ -1865,16 +1869,16 @@
     let var_name = CString::new(var_name).unwrap();
     let linkage_name = CString::new(linkage_name).unwrap();
     unsafe {
-        llvm::LLVMDIBuilderCreateStaticVariable(DIB(cx),
-                                                var_scope,
-                                                var_name.as_ptr(),
-                                                linkage_name.as_ptr(),
-                                                file_metadata,
-                                                line_number,
-                                                type_metadata,
-                                                is_local_to_unit,
-                                                global,
-                                                ptr::null_mut());
+        llvm::LLVMRustDIBuilderCreateStaticVariable(DIB(cx),
+                                                    var_scope,
+                                                    var_name.as_ptr(),
+                                                    linkage_name.as_ptr(),
+                                                    file_metadata,
+                                                    line_number,
+                                                    type_metadata,
+                                                    is_local_to_unit,
+                                                    global,
+                                                    ptr::null_mut());
     }
 }
 
@@ -1977,10 +1981,10 @@
                                                               env_index);
 
     let address_operations = unsafe {
-        [llvm::LLVMDIBuilderCreateOpDeref(),
-         llvm::LLVMDIBuilderCreateOpPlus(),
+        [llvm::LLVMRustDIBuilderCreateOpDeref(),
+         llvm::LLVMRustDIBuilderCreateOpPlus(),
          byte_offset_of_var_in_env as i64,
-         llvm::LLVMDIBuilderCreateOpDeref()]
+         llvm::LLVMRustDIBuilderCreateOpDeref()]
     };
 
     let address_op_count = if captured_by_ref {
@@ -2018,7 +2022,7 @@
 
     let scope_metadata = scope_metadata(bcx.fcx, binding.id, binding.span);
     let aops = unsafe {
-        [llvm::LLVMDIBuilderCreateOpDeref()]
+        [llvm::LLVMRustDIBuilderCreateOpDeref()]
     };
     // Regardless of the actual type (`T`) we're always passed the stack slot
     // (alloca) for the binding. For ByRef bindings that's a `T*` but for ByMove
diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs
index 8c5b3ed..464c32c 100644
--- a/src/librustc_trans/debuginfo/mod.rs
+++ b/src/librustc_trans/debuginfo/mod.rs
@@ -18,7 +18,7 @@
 use self::namespace::mangled_name_of_item;
 use self::type_names::compute_debuginfo_type_name;
 use self::metadata::{type_metadata, diverging_type_metadata};
-use self::metadata::{file_metadata, scope_metadata, TypeMap, compile_unit_metadata};
+use self::metadata::{file_metadata, scope_metadata, TypeMap};
 use self::source_loc::InternalDebugLocation::{self, UnknownLocation};
 
 use llvm;
@@ -32,6 +32,7 @@
 
 use abi::Abi;
 use common::{NodeIdAndSpan, CrateContext, FunctionContext, Block, BlockAndBuilder};
+use inline;
 use monomorphize::{self, Instance};
 use rustc::ty::{self, Ty};
 use session::config::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
@@ -50,7 +51,7 @@
 mod utils;
 mod namespace;
 mod type_names;
-mod metadata;
+pub mod metadata;
 mod create_scope_map;
 mod source_loc;
 
@@ -88,7 +89,7 @@
 impl<'tcx> CrateDebugContext<'tcx> {
     pub fn new(llmod: ModuleRef) -> CrateDebugContext<'tcx> {
         debug!("CrateDebugContext::new");
-        let builder = unsafe { llvm::LLVMDIBuilderCreate(llmod) };
+        let builder = unsafe { llvm::LLVMRustDIBuilderCreate(llmod) };
         // DIBuilder inherits context from the module, so we'd better use the same one
         let llcontext = unsafe { llvm::LLVMGetModuleContext(llmod) };
         return CrateDebugContext {
@@ -168,7 +169,6 @@
     }
 
     debug!("finalize");
-    let _ = compile_unit_metadata(cx);
 
     if gdb::needs_gdb_debug_scripts_section(cx) {
         // Add a .debug_gdb_scripts section to this compile-unit. This will
@@ -179,8 +179,8 @@
     }
 
     unsafe {
-        llvm::LLVMDIBuilderFinalize(DIB(cx));
-        llvm::LLVMDIBuilderDispose(DIB(cx));
+        llvm::LLVMRustDIBuilderFinalize(DIB(cx));
+        llvm::LLVMRustDIBuilderDispose(DIB(cx));
         // Debuginfo generation in LLVM by default uses a higher
         // version of dwarf than OS X currently understands. We can
         // instruct LLVM to emit an older version of dwarf, however,
@@ -239,6 +239,7 @@
     // Do this here already, in case we do an early exit from this function.
     source_loc::set_debug_location(cx, None, UnknownLocation);
 
+    let instance = inline::maybe_inline_instance(cx, instance);
     let (containing_scope, span) = get_containing_scope_and_span(cx, instance);
 
     // This can be the case for functions inlined from another crate
@@ -251,7 +252,7 @@
 
     let function_type_metadata = unsafe {
         let fn_signature = get_function_signature(cx, sig, abi);
-        llvm::LLVMDIBuilderCreateSubroutineType(DIB(cx), file_metadata, fn_signature)
+        llvm::LLVMRustDIBuilderCreateSubroutineType(DIB(cx), file_metadata, fn_signature)
     };
 
     // Find the enclosing function, in case this is a closure.
@@ -285,7 +286,7 @@
     let linkage_name = CString::new(linkage_name).unwrap();
 
     let fn_metadata = unsafe {
-        llvm::LLVMDIBuilderCreateFunction(
+        llvm::LLVMRustDIBuilderCreateFunction(
             DIB(cx),
             containing_scope,
             function_name.as_ptr(),
@@ -389,7 +390,7 @@
                 let actual_type_metadata = type_metadata(cx, actual_type, syntax_pos::DUMMY_SP);
                 let name = CString::new(param.name.as_str().as_bytes()).unwrap();
                 unsafe {
-                    llvm::LLVMDIBuilderCreateTemplateTypeParameter(
+                    llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
                         DIB(cx),
                         ptr::null_mut(),
                         name.as_ptr(),
@@ -439,10 +440,9 @@
         });
 
         // Try to get some span information, if we have an inlined item.
-        let definition_span = match cx.external().borrow().get(&instance.def) {
-            Some(&Some(node_id)) => cx.tcx().map.span(node_id),
-            _ => cx.tcx().map.def_id_span(instance.def, syntax_pos::DUMMY_SP)
-        };
+        let definition_span = cx.tcx()
+                                .map
+                                .def_id_span(instance.def, syntax_pos::DUMMY_SP);
 
         (containing_scope, definition_span)
     }
@@ -494,7 +494,7 @@
         (DirectVariable { alloca }, address_operations) |
         (IndirectVariable {alloca, address_operations}, _) => {
             let metadata = unsafe {
-                llvm::LLVMDIBuilderCreateVariable(
+                llvm::LLVMRustDIBuilderCreateVariable(
                     DIB(cx),
                     dwarf_tag,
                     scope_metadata,
@@ -512,7 +512,7 @@
                 InternalDebugLocation::new(scope_metadata, loc.line, loc.col.to_usize()));
             unsafe {
                 let debug_loc = llvm::LLVMGetCurrentDebugLocation(cx.raw_builder());
-                let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(
+                let instr = llvm::LLVMRustDIBuilderInsertDeclareAtEnd(
                     DIB(cx),
                     alloca,
                     metadata,
diff --git a/src/librustc_trans/debuginfo/namespace.rs b/src/librustc_trans/debuginfo/namespace.rs
index 167229d..5953ec4 100644
--- a/src/librustc_trans/debuginfo/namespace.rs
+++ b/src/librustc_trans/debuginfo/namespace.rs
@@ -10,7 +10,7 @@
 
 // Namespace Handling.
 
-use super::metadata::{file_metadata, NO_FILE_METADATA, UNKNOWN_LINE_NUMBER};
+use super::metadata::{file_metadata, unknown_file_metadata, UNKNOWN_LINE_NUMBER};
 use super::utils::{DIB, debug_context, span_start};
 
 use llvm;
@@ -74,11 +74,11 @@
         let loc = span_start(ccx, span);
         (file_metadata(ccx, &loc.file.name, &loc.file.abs_path), loc.line as c_uint)
     } else {
-        (NO_FILE_METADATA, UNKNOWN_LINE_NUMBER)
+        (unknown_file_metadata(ccx), UNKNOWN_LINE_NUMBER)
     };
 
     let scope = unsafe {
-        llvm::LLVMDIBuilderCreateNameSpace(
+        llvm::LLVMRustDIBuilderCreateNameSpace(
             DIB(ccx),
             parent_scope,
             namespace_name.as_ptr(),
diff --git a/src/librustc_trans/debuginfo/source_loc.rs b/src/librustc_trans/debuginfo/source_loc.rs
index 9726001..d288b9d 100644
--- a/src/librustc_trans/debuginfo/source_loc.rs
+++ b/src/librustc_trans/debuginfo/source_loc.rs
@@ -206,7 +206,7 @@
             debug!("setting debug location to {} {}", line, col);
 
             unsafe {
-                llvm::LLVMDIBuilderCreateDebugLocation(
+                llvm::LLVMRustDIBuilderCreateDebugLocation(
                     debug_context(cx).llcontext,
                     line as c_uint,
                     col as c_uint,
diff --git a/src/librustc_trans/debuginfo/utils.rs b/src/librustc_trans/debuginfo/utils.rs
index 1e0afa4..5734a12 100644
--- a/src/librustc_trans/debuginfo/utils.rs
+++ b/src/librustc_trans/debuginfo/utils.rs
@@ -40,7 +40,7 @@
 #[allow(non_snake_case)]
 pub fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray {
     return unsafe {
-        llvm::LLVMDIBuilderGetOrCreateArray(builder, arr.as_ptr(), arr.len() as u32)
+        llvm::LLVMRustDIBuilderGetOrCreateArray(builder, arr.as_ptr(), arr.len() as u32)
     };
 }
 
@@ -86,10 +86,7 @@
     });
 
     // Try to get some span information, if we have an inlined item.
-    let definition_span = match cx.external().borrow().get(&def_id) {
-        Some(&Some(node_id)) => cx.tcx().map.span(node_id),
-        _ => cx.tcx().map.def_id_span(def_id, syntax_pos::DUMMY_SP)
-    };
+    let definition_span = cx.tcx().map.def_id_span(def_id, syntax_pos::DUMMY_SP);
 
     (containing_scope, definition_span)
 }
diff --git a/src/librustc_trans/declare.rs b/src/librustc_trans/declare.rs
index 2746d3f..324e869 100644
--- a/src/librustc_trans/declare.rs
+++ b/src/librustc_trans/declare.rs
@@ -20,6 +20,7 @@
 //! * Use define_* family of methods when you might be defining the ValueRef.
 //! * When in doubt, define.
 use llvm::{self, ValueRef};
+use llvm::AttributePlace::Function;
 use rustc::ty;
 use abi::{Abi, FnType};
 use attributes;
@@ -40,7 +41,7 @@
         bug!("name {:?} contains an interior null byte", name)
     });
     unsafe {
-        llvm::LLVMGetOrInsertGlobal(ccx.llmod(), namebuf.as_ptr(), ty.to_ref())
+        llvm::LLVMRustGetOrInsertGlobal(ccx.llmod(), namebuf.as_ptr(), ty.to_ref())
     }
 }
 
@@ -55,7 +56,7 @@
         bug!("name {:?} contains an interior null byte", name)
     });
     let llfn = unsafe {
-        llvm::LLVMGetOrInsertFunction(ccx.llmod(), namebuf.as_ptr(), ty.to_ref())
+        llvm::LLVMRustGetOrInsertFunction(ccx.llmod(), namebuf.as_ptr(), ty.to_ref())
     };
 
     llvm::SetFunctionCallConv(llfn, callconv);
@@ -65,16 +66,16 @@
 
     if ccx.tcx().sess.opts.cg.no_redzone
         .unwrap_or(ccx.tcx().sess.target.target.options.disable_redzone) {
-        llvm::SetFunctionAttribute(llfn, llvm::Attribute::NoRedZone)
+        llvm::Attribute::NoRedZone.apply_llfn(Function, llfn);
     }
 
     match ccx.tcx().sess.opts.cg.opt_level.as_ref().map(String::as_ref) {
         Some("s") => {
-            llvm::SetFunctionAttribute(llfn, llvm::Attribute::OptimizeForSize);
+            llvm::Attribute::OptimizeForSize.apply_llfn(Function, llfn);
         },
         Some("z") => {
-            llvm::SetFunctionAttribute(llfn, llvm::Attribute::MinSize);
-            llvm::SetFunctionAttribute(llfn, llvm::Attribute::OptimizeForSize);
+            llvm::Attribute::MinSize.apply_llfn(Function, llfn);
+            llvm::Attribute::OptimizeForSize.apply_llfn(Function, llfn);
         },
         _ => {},
     }
@@ -111,7 +112,7 @@
     let llfn = declare_raw_fn(ccx, name, fty.cconv, fty.llvm_type(ccx));
 
     if sig.output == ty::FnDiverging {
-        llvm::SetFunctionAttribute(llfn, llvm::Attribute::NoReturn);
+        llvm::Attribute::NoReturn.apply_llfn(Function, llfn);
     }
 
     if abi != Abi::Rust && abi != Abi::RustCall {
@@ -162,7 +163,7 @@
                                     name: &str,
                                     fn_type: ty::Ty<'tcx>) -> ValueRef {
     let llfn = define_fn(ccx, name, fn_type);
-    llvm::SetLinkage(llfn, llvm::InternalLinkage);
+    unsafe { llvm::LLVMSetLinkage(llfn, llvm::InternalLinkage) };
     llfn
 }
 
@@ -173,7 +174,7 @@
     let namebuf = CString::new(name).unwrap_or_else(|_|{
         bug!("name {:?} contains an interior null byte", name)
     });
-    let val = unsafe { llvm::LLVMGetNamedValue(ccx.llmod(), namebuf.as_ptr()) };
+    let val = unsafe { llvm::LLVMRustGetNamedValue(ccx.llmod(), namebuf.as_ptr()) };
     if val.is_null() {
         debug!("get_declared_value: {:?} value is null", name);
         None
diff --git a/src/librustc_trans/glue.rs b/src/librustc_trans/glue.rs
index ef7d0ea..6bc4854 100644
--- a/src/librustc_trans/glue.rs
+++ b/src/librustc_trans/glue.rs
@@ -239,7 +239,7 @@
                     Falling back to on-demand instantiation.",
                     g,
                     TransItem::DropGlue(g).to_raw_string(),
-                    ccx.codegen_unit().name);
+                    ccx.codegen_unit().name());
 
             ccx.stats().n_fallback_instantiations.set(ccx.stats()
                                                          .n_fallback_instantiations
diff --git a/src/librustc_trans/inline.rs b/src/librustc_trans/inline.rs
index 4077b89..8581fcc 100644
--- a/src/librustc_trans/inline.rs
+++ b/src/librustc_trans/inline.rs
@@ -8,14 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use middle::cstore::{FoundAst, InlinedItem};
 use rustc::hir::def_id::DefId;
 use base::push_ctxt;
 use common::*;
 use monomorphize::Instance;
 
 use rustc::dep_graph::DepNode;
-use rustc::hir;
 
 fn instantiate_inline(ccx: &CrateContext, fn_id: DefId) -> Option<DefId> {
     debug!("instantiate_inline({:?})", fn_id);
@@ -23,104 +21,12 @@
     let tcx = ccx.tcx();
     let _task = tcx.dep_graph.in_task(DepNode::TransInlinedItem(fn_id));
 
-    match ccx.external().borrow().get(&fn_id) {
-        Some(&Some(node_id)) => {
-            // Already inline
-            debug!("instantiate_inline({}): already inline as node id {}",
-                   tcx.item_path_str(fn_id), node_id);
-            let node_def_id = tcx.map.local_def_id(node_id);
-            return Some(node_def_id);
-        }
-        Some(&None) => {
-            return None; // Not inlinable
-        }
-        None => {
-            // Not seen yet
-        }
-    }
-
-    let inlined = tcx.sess.cstore.maybe_get_item_ast(tcx, fn_id);
-    let inline_id = match inlined {
-        FoundAst::NotFound => {
-            ccx.external().borrow_mut().insert(fn_id, None);
-            return None;
-        }
-        FoundAst::Found(&InlinedItem::Item(ref item)) => {
-            ccx.external().borrow_mut().insert(fn_id, Some(item.id));
-            ccx.external_srcs().borrow_mut().insert(item.id, fn_id);
-
-            ccx.stats().n_inlines.set(ccx.stats().n_inlines.get() + 1);
-
-            item.id
-        }
-        FoundAst::Found(&InlinedItem::Foreign(ref item)) => {
-            ccx.external().borrow_mut().insert(fn_id, Some(item.id));
-            ccx.external_srcs().borrow_mut().insert(item.id, fn_id);
-            item.id
-        }
-        FoundAst::FoundParent(parent_id, item) => {
-            ccx.external().borrow_mut().insert(parent_id, Some(item.id));
-            ccx.external_srcs().borrow_mut().insert(item.id, parent_id);
-
-            let mut my_id = 0;
-            match item.node {
-                hir::ItemEnum(ref ast_def, _) => {
-                    let ast_vs = &ast_def.variants;
-                    let ty_vs = &tcx.lookup_adt_def(parent_id).variants;
-                    assert_eq!(ast_vs.len(), ty_vs.len());
-                    for (ast_v, ty_v) in ast_vs.iter().zip(ty_vs.iter()) {
-                        if ty_v.did == fn_id { my_id = ast_v.node.data.id(); }
-                        ccx.external().borrow_mut().insert(ty_v.did, Some(ast_v.node.data.id()));
-                        ccx.external_srcs().borrow_mut().insert(ast_v.node.data.id(), ty_v.did);
-                    }
-                }
-                hir::ItemStruct(ref struct_def, _) => {
-                    if struct_def.is_struct() {
-                        bug!("instantiate_inline: called on a \
-                              non-tuple struct")
-                    } else {
-                        ccx.external().borrow_mut().insert(fn_id, Some(struct_def.id()));
-                        ccx.external_srcs().borrow_mut().insert(struct_def.id(), fn_id);
-                        my_id = struct_def.id();
-                    }
-                }
-                _ => bug!("instantiate_inline: item has a \
-                           non-enum, non-struct parent")
-            }
-            my_id
-        }
-        FoundAst::Found(&InlinedItem::TraitItem(_, ref trait_item)) => {
-            ccx.external().borrow_mut().insert(fn_id, Some(trait_item.id));
-            ccx.external_srcs().borrow_mut().insert(trait_item.id, fn_id);
-
-            ccx.stats().n_inlines.set(ccx.stats().n_inlines.get() + 1);
-
-            // Associated consts already have to be evaluated in `typeck`, so
-            // the logic to do that already exists in `middle`. In order to
-            // reuse that code, it needs to be able to look up the traits for
-            // inlined items.
-            let ty_trait_item = tcx.impl_or_trait_item(fn_id).clone();
-            let trait_item_def_id = tcx.map.local_def_id(trait_item.id);
-            tcx.impl_or_trait_items.borrow_mut()
-               .insert(trait_item_def_id, ty_trait_item);
-
-            // If this is a default method, we can't look up the
-            // impl type. But we aren't going to translate anyways, so
-            // don't.
-            trait_item.id
-        }
-        FoundAst::Found(&InlinedItem::ImplItem(_, ref impl_item)) => {
-            ccx.external().borrow_mut().insert(fn_id, Some(impl_item.id));
-            ccx.external_srcs().borrow_mut().insert(impl_item.id, fn_id);
-
-            ccx.stats().n_inlines.set(ccx.stats().n_inlines.get() + 1);
-
-            impl_item.id
-        }
-    };
-
-    let inline_def_id = tcx.map.local_def_id(inline_id);
-    Some(inline_def_id)
+    tcx.sess
+       .cstore
+       .maybe_get_item_ast(tcx, fn_id)
+       .map(|(_, inline_id)| {
+            tcx.map.local_def_id(inline_id)
+       })
 }
 
 pub fn get_local_instance(ccx: &CrateContext, fn_id: DefId)
diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs
index f033b27..2f27aed 100644
--- a/src/librustc_trans/intrinsic.rs
+++ b/src/librustc_trans/intrinsic.rs
@@ -19,7 +19,6 @@
 use rustc::ty::subst::FnSpace;
 use abi::{Abi, FnType};
 use adt;
-use attributes;
 use base::*;
 use build::*;
 use callee::{self, Callee};
@@ -37,13 +36,13 @@
 use type_::Type;
 use rustc::ty::{self, Ty};
 use Disr;
-use rustc::ty::subst::Substs;
 use rustc::hir;
 use syntax::ast;
 use syntax::ptr::P;
 use syntax::parse::token;
 
 use rustc::session::Session;
+use rustc_const_eval::fatal_const_eval_err;
 use syntax_pos::{Span, DUMMY_SP};
 
 use std::cmp::Ordering;
@@ -641,28 +640,30 @@
         // This requires that atomic intrinsics follow a specific naming pattern:
         // "atomic_<operation>[_<ordering>]", and no ordering means SeqCst
         (_, name) if name.starts_with("atomic_") => {
+            use llvm::AtomicOrdering::*;
+
             let split: Vec<&str> = name.split('_').collect();
 
             let is_cxchg = split[1] == "cxchg" || split[1] == "cxchgweak";
             let (order, failorder) = match split.len() {
-                2 => (llvm::SequentiallyConsistent, llvm::SequentiallyConsistent),
+                2 => (SequentiallyConsistent, SequentiallyConsistent),
                 3 => match split[2] {
-                    "unordered" => (llvm::Unordered, llvm::Unordered),
-                    "relaxed" => (llvm::Monotonic, llvm::Monotonic),
-                    "acq"     => (llvm::Acquire, llvm::Acquire),
-                    "rel"     => (llvm::Release, llvm::Monotonic),
-                    "acqrel"  => (llvm::AcquireRelease, llvm::Acquire),
+                    "unordered" => (Unordered, Unordered),
+                    "relaxed" => (Monotonic, Monotonic),
+                    "acq"     => (Acquire, Acquire),
+                    "rel"     => (Release, Monotonic),
+                    "acqrel"  => (AcquireRelease, Acquire),
                     "failrelaxed" if is_cxchg =>
-                        (llvm::SequentiallyConsistent, llvm::Monotonic),
+                        (SequentiallyConsistent, Monotonic),
                     "failacq" if is_cxchg =>
-                        (llvm::SequentiallyConsistent, llvm::Acquire),
+                        (SequentiallyConsistent, Acquire),
                     _ => ccx.sess().fatal("unknown ordering in atomic intrinsic")
                 },
                 4 => match (split[2], split[3]) {
                     ("acq", "failrelaxed") if is_cxchg =>
-                        (llvm::Acquire, llvm::Monotonic),
+                        (Acquire, Monotonic),
                     ("acqrel", "failrelaxed") if is_cxchg =>
-                        (llvm::AcquireRelease, llvm::Monotonic),
+                        (AcquireRelease, Monotonic),
                     _ => ccx.sess().fatal("unknown ordering in atomic intrinsic")
                 },
                 _ => ccx.sess().fatal("Atomic intrinsic not in correct format"),
@@ -715,12 +716,12 @@
                 }
 
                 "fence" => {
-                    AtomicFence(bcx, order, llvm::CrossThread);
+                    AtomicFence(bcx, order, llvm::SynchronizationScope::CrossThread);
                     C_nil(ccx)
                 }
 
                 "singlethreadfence" => {
-                    AtomicFence(bcx, order, llvm::SingleThread);
+                    AtomicFence(bcx, order, llvm::SynchronizationScope::SingleThread);
                     C_nil(ccx)
                 }
 
@@ -1172,7 +1173,6 @@
                              dloc: DebugLoc) -> Block<'blk, 'tcx> {
     let llfn = get_rust_try_fn(bcx.fcx, &mut |bcx| {
         let ccx = bcx.ccx();
-        let tcx = ccx.tcx();
         let dloc = DebugLoc::None;
 
         // Translates the shims described above:
@@ -1192,20 +1192,6 @@
         // expected to be `*mut *mut u8` for this to actually work, but that's
         // managed by the standard library.
 
-        attributes::emit_uwtable(bcx.fcx.llfn, true);
-        let target = &bcx.sess().target.target;
-        let catch_pers = if target.arch == "arm" && target.target_os != "ios" {
-            // Only ARM still uses a separate catch personality (for now)
-            match tcx.lang_items.eh_personality_catch() {
-                Some(did) => {
-                    Callee::def(ccx, did, tcx.mk_substs(Substs::empty())).reify(ccx).val
-                }
-                None => bug!("eh_personality_catch not defined"),
-            }
-        } else {
-            bcx.fcx.eh_personality()
-        };
-
         let then = bcx.fcx.new_temp_block("then");
         let catch = bcx.fcx.new_temp_block("catch");
 
@@ -1223,7 +1209,7 @@
         // rust_try ignores the selector.
         let lpad_ty = Type::struct_(ccx, &[Type::i8p(ccx), Type::i32(ccx)],
                                     false);
-        let vals = LandingPad(catch, lpad_ty, catch_pers, 1);
+        let vals = LandingPad(catch, lpad_ty, bcx.fcx.eh_personality(), 1);
         AddClause(catch, vals, C_null(Type::i8p(ccx)));
         let ptr = ExtractValue(catch, vals, 0);
         Store(catch, ptr, BitCast(catch, local_ptr, Type::i8p(ccx).ptr_to()));
@@ -1414,7 +1400,10 @@
                                          // this should probably help simd error reporting
                                          consts::TrueConst::Yes) {
                     Ok((vector, _)) => vector,
-                    Err(err) => bcx.sess().span_fatal(span, &err.description()),
+                    Err(err) => {
+                        fatal_const_eval_err(bcx.tcx(), err.as_inner(), span,
+                                             "shuffle indices");
+                    }
                 }
             }
             None => llargs[2]
diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs
index fa0a1fd..81a1dbe 100644
--- a/src/librustc_trans/lib.rs
+++ b/src/librustc_trans/lib.rs
@@ -37,6 +37,8 @@
 #![feature(unicode)]
 #![feature(question_mark)]
 
+use rustc::dep_graph::WorkProduct;
+
 extern crate arena;
 extern crate flate;
 extern crate getopts;
@@ -86,6 +88,7 @@
 mod abi;
 mod adt;
 mod asm;
+mod assert_module_sources;
 mod attributes;
 mod base;
 mod basic_block;
@@ -132,7 +135,27 @@
 
 #[derive(Clone)]
 pub struct ModuleTranslation {
+    /// The name of the module. When the crate may be saved between
+    /// compilations, incremental compilation requires that name be
+    /// unique amongst **all** crates.  Therefore, it should contain
+    /// something unique to this crate (e.g., a module path) as well
+    /// as the crate name and disambiguator.
     pub name: String,
+    pub symbol_name_hash: u64,
+    pub source: ModuleSource,
+}
+
+#[derive(Clone)]
+pub enum ModuleSource {
+    /// Copy the `.o` files or whatever from the incr. comp. directory.
+    Preexisting(WorkProduct),
+
+    /// Rebuild from this LLVM module.
+    Translated(ModuleLlvm),
+}
+
+#[derive(Copy, Clone)]
+pub struct ModuleLlvm {
     pub llcx: llvm::ContextRef,
     pub llmod: llvm::ModuleRef,
 }
diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs
index 7a7f190..2d1769b 100644
--- a/src/librustc_trans/mir/block.rs
+++ b/src/librustc_trans/mir/block.rs
@@ -284,6 +284,7 @@
 
                 // After this point, bcx is the block for the call to panic.
                 bcx = panic_block.build();
+                debug_loc.apply_to_bcx(&bcx);
 
                 // Get the location information.
                 let loc = bcx.sess().codemap().lookup_char_pos(span.lo);
diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs
index da72793..00db19d 100644
--- a/src/librustc_trans/mir/constant.rs
+++ b/src/librustc_trans/mir/constant.rs
@@ -530,26 +530,10 @@
 
                 // FIXME Shouldn't need to manually trigger closure instantiations.
                 if let mir::AggregateKind::Closure(def_id, substs) = *kind {
-                    use rustc::hir;
-                    use syntax::ast::DUMMY_NODE_ID;
-                    use syntax::ptr::P;
                     use closure;
-
-                    closure::trans_closure_expr(closure::Dest::Ignore(self.ccx),
-                                                &hir::FnDecl {
-                                                    inputs: P::new(),
-                                                    output: hir::NoReturn(DUMMY_SP),
-                                                    variadic: false
-                                                },
-                                                &hir::Block {
-                                                    stmts: P::new(),
-                                                    expr: None,
-                                                    id: DUMMY_NODE_ID,
-                                                    rules: hir::DefaultBlock,
-                                                    span: DUMMY_SP
-                                                },
-                                                DUMMY_NODE_ID, def_id,
-                                                self.monomorphize(&substs));
+                    closure::trans_closure_body_via_mir(self.ccx,
+                                                        def_id,
+                                                        self.monomorphize(&substs));
                 }
 
                 let val = if let mir::AggregateKind::Adt(adt_def, index, _) = *kind {
@@ -840,11 +824,11 @@
             mir::BinOp::Gt | mir::BinOp::Ge => {
                 if is_float {
                     let cmp = base::bin_op_to_fcmp_predicate(op.to_hir_binop());
-                    llvm::ConstFCmp(cmp, lhs, rhs)
+                    llvm::LLVMConstFCmp(cmp, lhs, rhs)
                 } else {
                     let cmp = base::bin_op_to_icmp_predicate(op.to_hir_binop(),
                                                                 signed);
-                    llvm::ConstICmp(cmp, lhs, rhs)
+                    llvm::LLVMConstICmp(cmp, lhs, rhs)
                 }
             }
         }
@@ -925,7 +909,7 @@
             }
             Err(ConstEvalFailure::Runtime(err)) => {
                 span_bug!(constant.span,
-                          "MIR constant {:?} results in runtime panic: {}",
+                          "MIR constant {:?} results in runtime panic: {:?}",
                           constant, err.description())
             }
         }
diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs
index 0221232..8f723d2 100644
--- a/src/librustc_trans/mir/mod.rs
+++ b/src/librustc_trans/mir/mod.rs
@@ -324,8 +324,8 @@
                         machine::llelement_offset(bcx.ccx(), lltuplety, i);
 
                     let ops = unsafe {
-                        [llvm::LLVMDIBuilderCreateOpDeref(),
-                         llvm::LLVMDIBuilderCreateOpPlus(),
+                        [llvm::LLVMRustDIBuilderCreateOpDeref(),
+                         llvm::LLVMRustDIBuilderCreateOpPlus(),
                          byte_offset_of_var_in_tuple as i64]
                     };
 
@@ -450,10 +450,10 @@
                     machine::llelement_offset(bcx.ccx(), llclosurety, i);
 
                 let ops = unsafe {
-                    [llvm::LLVMDIBuilderCreateOpDeref(),
-                     llvm::LLVMDIBuilderCreateOpPlus(),
+                    [llvm::LLVMRustDIBuilderCreateOpDeref(),
+                     llvm::LLVMRustDIBuilderCreateOpPlus(),
                      byte_offset_of_var_in_env as i64,
-                     llvm::LLVMDIBuilderCreateOpDeref()]
+                     llvm::LLVMRustDIBuilderCreateOpDeref()]
                 };
 
                 // The environment and the capture can each be indirect.
diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs
index c3f2c4f..97d65ce 100644
--- a/src/librustc_trans/mir/rvalue.rs
+++ b/src/librustc_trans/mir/rvalue.rs
@@ -131,27 +131,11 @@
                     _ => {
                         // FIXME Shouldn't need to manually trigger closure instantiations.
                         if let mir::AggregateKind::Closure(def_id, substs) = *kind {
-                            use rustc::hir;
-                            use syntax::ast::DUMMY_NODE_ID;
-                            use syntax::ptr::P;
-                            use syntax_pos::DUMMY_SP;
                             use closure;
 
-                            closure::trans_closure_expr(closure::Dest::Ignore(bcx.ccx()),
-                                                        &hir::FnDecl {
-                                                            inputs: P::new(),
-                                                            output: hir::NoReturn(DUMMY_SP),
-                                                            variadic: false
-                                                        },
-                                                        &hir::Block {
-                                                            stmts: P::new(),
-                                                            expr: None,
-                                                            id: DUMMY_NODE_ID,
-                                                            rules: hir::DefaultBlock,
-                                                            span: DUMMY_SP
-                                                        },
-                                                        DUMMY_NODE_ID, def_id,
-                                                        bcx.monomorphize(&substs));
+                            closure::trans_closure_body_via_mir(bcx.ccx(),
+                                                                def_id,
+                                                                bcx.monomorphize(&substs));
                         }
 
                         for (i, operand) in operands.iter().enumerate() {
@@ -260,18 +244,46 @@
                             }
                         }
                     }
-                    mir::CastKind::Misc if common::type_is_immediate(bcx.ccx(), operand.ty) => {
+                    mir::CastKind::Misc if common::type_is_fat_ptr(bcx.tcx(), operand.ty) => {
+                        let ll_cast_ty = type_of::immediate_type_of(bcx.ccx(), cast_ty);
+                        let ll_from_ty = type_of::immediate_type_of(bcx.ccx(), operand.ty);
+                        if let OperandValue::Pair(data_ptr, meta_ptr) = operand.val {
+                            if common::type_is_fat_ptr(bcx.tcx(), cast_ty) {
+                                let ll_cft = ll_cast_ty.field_types();
+                                let ll_fft = ll_from_ty.field_types();
+                                let data_cast = bcx.pointercast(data_ptr, ll_cft[0]);
+                                assert_eq!(ll_cft[1].kind(), ll_fft[1].kind());
+                                OperandValue::Pair(data_cast, meta_ptr)
+                            } else { // cast to thin-ptr
+                                // Cast of fat-ptr to thin-ptr is an extraction of data-ptr and
+                                // pointer-cast of that pointer to desired pointer type.
+                                let llval = bcx.pointercast(data_ptr, ll_cast_ty);
+                                OperandValue::Immediate(llval)
+                            }
+                        } else {
+                            bug!("Unexpected non-Pair operand")
+                        }
+                    }
+                    mir::CastKind::Misc => {
                         debug_assert!(common::type_is_immediate(bcx.ccx(), cast_ty));
                         let r_t_in = CastTy::from_ty(operand.ty).expect("bad input type for cast");
                         let r_t_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
                         let ll_t_in = type_of::immediate_type_of(bcx.ccx(), operand.ty);
                         let ll_t_out = type_of::immediate_type_of(bcx.ccx(), cast_ty);
-                        let llval = operand.immediate();
-                        let signed = if let CastTy::Int(IntTy::CEnum) = r_t_in {
+                        let (llval, signed) = if let CastTy::Int(IntTy::CEnum) = r_t_in {
                             let repr = adt::represent_type(bcx.ccx(), operand.ty);
-                            adt::is_discr_signed(&repr)
+                            let discr = match operand.val {
+                                OperandValue::Immediate(llval) => llval,
+                                OperandValue::Ref(llptr) => {
+                                    bcx.with_block(|bcx| {
+                                        adt::trans_get_discr(bcx, &repr, llptr, None, true)
+                                    })
+                                }
+                                OperandValue::Pair(..) => bug!("Unexpected Pair operand")
+                            };
+                            (discr, adt::is_discr_signed(&repr))
                         } else {
-                            operand.ty.is_signed()
+                            (operand.immediate(), operand.ty.is_signed())
                         };
 
                         let newval = match (r_t_in, r_t_out) {
@@ -320,26 +332,6 @@
                         };
                         OperandValue::Immediate(newval)
                     }
-                    mir::CastKind::Misc => { // Casts from a fat-ptr.
-                        let ll_cast_ty = type_of::immediate_type_of(bcx.ccx(), cast_ty);
-                        let ll_from_ty = type_of::immediate_type_of(bcx.ccx(), operand.ty);
-                        if let OperandValue::Pair(data_ptr, meta_ptr) = operand.val {
-                            if common::type_is_fat_ptr(bcx.tcx(), cast_ty) {
-                                let ll_cft = ll_cast_ty.field_types();
-                                let ll_fft = ll_from_ty.field_types();
-                                let data_cast = bcx.pointercast(data_ptr, ll_cft[0]);
-                                assert_eq!(ll_cft[1].kind(), ll_fft[1].kind());
-                                OperandValue::Pair(data_cast, meta_ptr)
-                            } else { // cast to thin-ptr
-                                // Cast of fat-ptr to thin-ptr is an extraction of data-ptr and
-                                // pointer-cast of that pointer to desired pointer type.
-                                let llval = bcx.pointercast(data_ptr, ll_cast_ty);
-                                OperandValue::Immediate(llval)
-                            }
-                        } else {
-                            bug!("Unexpected non-Pair operand")
-                        }
-                    }
                 };
                 let operand = OperandRef {
                     val: val,
diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans/monomorphize.rs
index 00c0e91..e9aacaa 100644
--- a/src/librustc_trans/monomorphize.rs
+++ b/src/librustc_trans/monomorphize.rs
@@ -52,7 +52,7 @@
         debug!("leaving monomorphic fn {:?}", instance);
         return (val, mono_ty);
     } else {
-        assert!(!ccx.codegen_unit().items.contains_key(&TransItem::Fn(instance)));
+        assert!(!ccx.codegen_unit().contains_item(&TransItem::Fn(instance)));
     }
 
     debug!("monomorphic_fn({:?})", instance);
@@ -125,7 +125,9 @@
 
             if ccx.shared().translation_items().borrow().contains(&trans_item) {
                 attributes::from_fn_attrs(ccx, attrs, lldecl);
-                llvm::SetLinkage(lldecl, llvm::ExternalLinkage);
+                unsafe {
+                    llvm::LLVMSetLinkage(lldecl, llvm::ExternalLinkage);
+                }
             } else {
                 // FIXME: #34151
                 // Normally, getting here would indicate a bug in trans::collector,
diff --git a/src/librustc_trans/partitioning.rs b/src/librustc_trans/partitioning.rs
index 8073359..ade6e8a 100644
--- a/src/librustc_trans/partitioning.rs
+++ b/src/librustc_trans/partitioning.rs
@@ -119,12 +119,15 @@
 use collector::InliningMap;
 use llvm;
 use monomorphize;
+use rustc::dep_graph::{DepNode, WorkProductId};
 use rustc::hir::def_id::DefId;
 use rustc::hir::map::DefPathData;
 use rustc::session::config::NUMBERED_CODEGEN_UNIT_MARKER;
 use rustc::ty::TyCtxt;
 use rustc::ty::item_path::characteristic_def_id_of_type;
 use std::cmp::Ordering;
+use std::hash::{Hash, Hasher, SipHasher};
+use std::sync::Arc;
 use symbol_map::SymbolMap;
 use syntax::ast::NodeId;
 use syntax::parse::token::{self, InternedString};
@@ -140,11 +143,59 @@
 }
 
 pub struct CodegenUnit<'tcx> {
-    pub name: InternedString,
-    pub items: FnvHashMap<TransItem<'tcx>, llvm::Linkage>,
+    /// A name for this CGU. Incremental compilation requires that
+    /// name be unique amongst **all** crates.  Therefore, it should
+    /// contain something unique to this crate (e.g., a module path)
+    /// as well as the crate name and disambiguator.
+    name: InternedString,
+
+    items: FnvHashMap<TransItem<'tcx>, llvm::Linkage>,
 }
 
 impl<'tcx> CodegenUnit<'tcx> {
+    pub fn new(name: InternedString,
+               items: FnvHashMap<TransItem<'tcx>, llvm::Linkage>)
+               -> Self {
+        CodegenUnit {
+            name: name,
+            items: items,
+        }
+    }
+
+    pub fn empty(name: InternedString) -> Self {
+        Self::new(name, FnvHashMap())
+    }
+
+    pub fn contains_item(&self, item: &TransItem<'tcx>) -> bool {
+        self.items.contains_key(item)
+    }
+
+    pub fn name(&self) -> &str {
+        &self.name
+    }
+
+    pub fn items(&self) -> &FnvHashMap<TransItem<'tcx>, llvm::Linkage> {
+        &self.items
+    }
+
+    pub fn work_product_id(&self) -> Arc<WorkProductId> {
+        Arc::new(WorkProductId(self.name().to_string()))
+    }
+
+    pub fn work_product_dep_node(&self) -> DepNode<DefId> {
+        DepNode::WorkProduct(self.work_product_id())
+    }
+
+    pub fn compute_symbol_name_hash(&self, tcx: TyCtxt, symbol_map: &SymbolMap) -> u64 {
+        let mut state = SipHasher::new();
+        let all_items = self.items_in_deterministic_order(tcx, symbol_map);
+        for (item, _) in all_items {
+            let symbol_name = symbol_map.get(item).unwrap();
+            symbol_name.hash(&mut state);
+        }
+        state.finish()
+    }
+
     pub fn items_in_deterministic_order(&self,
                                         tcx: TyCtxt,
                                         symbol_map: &SymbolMap)
@@ -277,10 +328,7 @@
             };
 
             let make_codegen_unit = || {
-                CodegenUnit {
-                    name: codegen_unit_name.clone(),
-                    items: FnvHashMap(),
-                }
+                CodegenUnit::empty(codegen_unit_name.clone())
             };
 
             let mut codegen_unit = codegen_units.entry(codegen_unit_name.clone())
@@ -319,10 +367,7 @@
     if codegen_units.is_empty() {
         let codegen_unit_name = InternedString::new(FALLBACK_CODEGEN_UNIT);
         codegen_units.entry(codegen_unit_name.clone())
-                     .or_insert_with(|| CodegenUnit {
-                         name: codegen_unit_name.clone(),
-                         items: FnvHashMap(),
-                     });
+                     .or_insert_with(|| CodegenUnit::empty(codegen_unit_name.clone()));
     }
 
     PreInliningPartitioning {
@@ -362,10 +407,8 @@
     // we reach the target count
     while codegen_units.len() < target_cgu_count {
         let index = codegen_units.len();
-        codegen_units.push(CodegenUnit {
-            name: numbered_codegen_unit_name(crate_name, index),
-            items: FnvHashMap()
-        });
+        codegen_units.push(
+            CodegenUnit::empty(numbered_codegen_unit_name(crate_name, index)));
     }
 }
 
@@ -381,10 +424,8 @@
             follow_inlining(*root, inlining_map, &mut reachable);
         }
 
-        let mut new_codegen_unit = CodegenUnit {
-            name: codegen_unit.name.clone(),
-            items: FnvHashMap(),
-        };
+        let mut new_codegen_unit =
+            CodegenUnit::empty(codegen_unit.name.clone());
 
         // Add all translation items that are not already there
         for trans_item in reachable {
@@ -560,10 +601,9 @@
         items.insert(trans_item, linkage);
     }
 
-    CodegenUnit {
-        name: numbered_codegen_unit_name(&tcx.crate_name[..], 0),
-        items: items
-    }
+    CodegenUnit::new(
+        numbered_codegen_unit_name(&tcx.crate_name[..], 0),
+        items)
 }
 
 fn numbered_codegen_unit_name(crate_name: &str, index: usize) -> InternedString {
diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs
index 8b8e658..35bb048 100644
--- a/src/librustc_trans/trans_item.rs
+++ b/src/librustc_trans/trans_item.rs
@@ -23,12 +23,13 @@
 use llvm;
 use monomorphize::{self, Instance};
 use inline;
+use rustc::dep_graph::DepNode;
 use rustc::hir;
 use rustc::hir::map as hir_map;
 use rustc::hir::def_id::DefId;
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc::ty::subst;
-use rustc::dep_graph::DepNode;
+use rustc_const_eval::fatal_const_eval_err;
 use std::hash::{Hash, Hasher};
 use syntax::ast::{self, NodeId};
 use syntax::{attr,errors};
@@ -67,27 +68,45 @@
 impl<'a, 'tcx> TransItem<'tcx> {
 
     pub fn define(&self, ccx: &CrateContext<'a, 'tcx>) {
-
         debug!("BEGIN IMPLEMENTING '{} ({})' in cgu {}",
                   self.to_string(ccx.tcx()),
                   self.to_raw_string(),
-                  ccx.codegen_unit().name);
+                  ccx.codegen_unit().name());
+
+        // (*) This code executes in the context of a dep-node for the
+        // entire CGU. In some cases, we introduce dep-nodes for
+        // particular items that we are translating (these nodes will
+        // have read edges coming into the CGU node). These smaller
+        // nodes are not needed for correctness -- we always
+        // invalidate an entire CGU at a time -- but they enable
+        // finer-grained testing, since you can write tests that check
+        // that the incoming edges to a particular fn are from a
+        // particular set.
 
         self.register_reads(ccx);
 
         match *self {
             TransItem::Static(node_id) => {
+                let def_id = ccx.tcx().map.local_def_id(node_id);
+                let _task = ccx.tcx().dep_graph.in_task(DepNode::TransCrateItem(def_id)); // (*)
                 let item = ccx.tcx().map.expect_item(node_id);
                 if let hir::ItemStatic(_, m, ref expr) = item.node {
                     match consts::trans_static(&ccx, m, expr, item.id, &item.attrs) {
                         Ok(_) => { /* Cool, everything's alright. */ },
-                        Err(err) => ccx.tcx().sess.span_fatal(expr.span, &err.description()),
+                        Err(err) => {
+                            // FIXME: shouldn't this be a `span_err`?
+                            fatal_const_eval_err(
+                                ccx.tcx(), &err, expr.span, "static");
+                        }
                     };
                 } else {
                     span_bug!(item.span, "Mismatch between hir::Item type and TransItem type")
                 }
             }
             TransItem::Fn(instance) => {
+                let _task = ccx.tcx().dep_graph.in_task(
+                    DepNode::TransCrateItem(instance.def)); // (*)
+
                 base::trans_instance(&ccx, instance);
             }
             TransItem::DropGlue(dg) => {
@@ -98,7 +117,7 @@
         debug!("END IMPLEMENTING '{} ({})' in cgu {}",
                self.to_string(ccx.tcx()),
                self.to_raw_string(),
-               ccx.codegen_unit().name);
+               ccx.codegen_unit().name());
     }
 
     /// If necessary, creates a subtask for trans'ing a particular item and registers reads on
@@ -147,7 +166,7 @@
         debug!("BEGIN PREDEFINING '{} ({})' in cgu {}",
                self.to_string(ccx.tcx()),
                self.to_raw_string(),
-               ccx.codegen_unit().name);
+               ccx.codegen_unit().name());
 
         let symbol_name = ccx.symbol_map()
                              .get_or_compute(ccx.shared(), *self);
@@ -169,7 +188,7 @@
         debug!("END PREDEFINING '{} ({})' in cgu {}",
                self.to_string(ccx.tcx()),
                self.to_raw_string(),
-               ccx.codegen_unit().name);
+               ccx.codegen_unit().name());
     }
 
     fn predefine_static(ccx: &CrateContext<'a, 'tcx>,
@@ -189,7 +208,7 @@
                         &format!("symbol `{}` is already defined", symbol_name))
                 });
 
-                llvm::SetLinkage(g, linkage);
+                unsafe { llvm::LLVMSetLinkage(g, linkage) };
             }
 
             item => bug!("predefine_static: expected static, found {:?}", item)
@@ -231,7 +250,7 @@
                 ref attrs, node: hir::ImplItemKind::Method(..), ..
             }) => {
                 let lldecl = declare::declare_fn(ccx, symbol_name, mono_ty);
-                llvm::SetLinkage(lldecl, linkage);
+                unsafe { llvm::LLVMSetLinkage(lldecl, linkage) };
                 base::set_link_section(ccx, lldecl, attrs);
                 if linkage == llvm::LinkOnceODRLinkage ||
                    linkage == llvm::WeakODRLinkage {
@@ -268,7 +287,7 @@
 
         assert!(declare::get_defined_value(ccx, symbol_name).is_none());
         let llfn = declare::declare_cfn(ccx, symbol_name, llfnty);
-        llvm::SetLinkage(llfn, linkage);
+        unsafe { llvm::LLVMSetLinkage(llfn, linkage) };
         if linkage == llvm::LinkOnceODRLinkage ||
            linkage == llvm::WeakODRLinkage {
             llvm::SetUniqueComdat(ccx.llmod(), llfn);
diff --git a/src/librustc_trans/tvec.rs b/src/librustc_trans/tvec.rs
index f5b9bef..92a2d37 100644
--- a/src/librustc_trans/tvec.rs
+++ b/src/librustc_trans/tvec.rs
@@ -30,7 +30,7 @@
 use rustc::ty::{self, Ty};
 
 use rustc::hir;
-use rustc_const_eval::eval_repeat_count;
+use rustc_const_eval::eval_length;
 
 use syntax::ast;
 use syntax::parse::token::InternedString;
@@ -218,7 +218,7 @@
                     return expr::trans_into(bcx, &element, Ignore);
                 }
                 SaveIn(lldest) => {
-                    match eval_repeat_count(bcx.tcx(), &count_expr) {
+                    match eval_length(bcx.tcx(), &count_expr, "repeat count").unwrap() {
                         0 => expr::trans_into(bcx, &element, Ignore),
                         1 => expr::trans_into(bcx, &element, SaveIn(lldest)),
                         count => {
@@ -268,7 +268,7 @@
         },
         hir::ExprVec(ref es) => es.len(),
         hir::ExprRepeat(_, ref count_expr) => {
-            eval_repeat_count(bcx.tcx(), &count_expr)
+            eval_length(bcx.tcx(), &count_expr, "repeat count").unwrap()
         }
         _ => span_bug!(content_expr.span, "unexpected vec content")
     }
diff --git a/src/librustc_trans/type_.rs b/src/librustc_trans/type_.rs
index 001cd19..d191591 100644
--- a/src/librustc_trans/type_.rs
+++ b/src/librustc_trans/type_.rs
@@ -36,7 +36,7 @@
 impl fmt::Debug for Type {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.write_str(&llvm::build_string(|s| unsafe {
-            llvm::LLVMWriteTypeToString(self.to_ref(), s);
+            llvm::LLVMRustWriteTypeToString(self.to_ref(), s);
         }).expect("non-UTF8 type description from LLVM"))
     }
 }
@@ -72,7 +72,7 @@
     }
 
     pub fn metadata(ccx: &CrateContext) -> Type {
-        ty!(llvm::LLVMMetadataTypeInContext(ccx.llcx()))
+        ty!(llvm::LLVMRustMetadataTypeInContext(ccx.llcx()))
     }
 
     pub fn i1(ccx: &CrateContext) -> Type {
@@ -208,7 +208,7 @@
 
     pub fn kind(&self) -> TypeKind {
         unsafe {
-            llvm::LLVMGetTypeKind(self.to_ref())
+            llvm::LLVMRustGetTypeKind(self.to_ref())
         }
     }
 
diff --git a/src/librustc_trans/value.rs b/src/librustc_trans/value.rs
index 00b316c..79e0c11 100644
--- a/src/librustc_trans/value.rs
+++ b/src/librustc_trans/value.rs
@@ -23,7 +23,7 @@
 impl fmt::Debug for Value {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.write_str(&llvm::build_string(|s| unsafe {
-            llvm::LLVMWriteValueToString(self.0, s);
+            llvm::LLVMRustWriteValueToString(self.0, s);
         }).expect("nun-UTF8 value description from LLVM"))
     }
 }
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 9ff30f9..3b2bca4 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -48,10 +48,7 @@
 //! case but `&a` in the second.  Basically, defaults that appear inside
 //! an rptr (`&r.T`) use the region `r` that appears in the rptr.
 
-use middle::const_val::ConstVal;
-use rustc_const_eval::{eval_const_expr_partial, ConstEvalErr};
-use rustc_const_eval::EvalHint::UncheckedExprHint;
-use rustc_const_eval::ErrKind::ErroneousReferencedConstant;
+use rustc_const_eval::eval_length;
 use hir::{self, SelfKind};
 use hir::def::{Def, PathResolution};
 use hir::def_id::DefId;
@@ -70,7 +67,6 @@
 use util::common::{ErrorReported, FN_OUTPUT_NAME};
 use util::nodemap::{NodeMap, FnvHashSet};
 
-use rustc_const_math::ConstInt;
 use std::cell::RefCell;
 use syntax::{abi, ast};
 use syntax::feature_gate::{GateIssue, emit_feature_err};
@@ -1317,6 +1313,12 @@
         // item is declared.
         let bound = match (&ty.sty, ty_path_def) {
             (_, Def::SelfTy(Some(trait_did), Some(impl_id))) => {
+                // For Def::SelfTy() values inlined from another crate, the
+                // impl_id will be DUMMY_NODE_ID, which would cause problems
+                // here. But we should never run into an impl from another crate
+                // in this pass.
+                assert!(impl_id != ast::DUMMY_NODE_ID);
+
                 // `Self` in an impl of a trait - we have a concrete self type and a
                 // trait reference.
                 let trait_ref = tcx.impl_trait_ref(tcx.map.local_def_id(impl_id)).unwrap();
@@ -1522,6 +1524,13 @@
             }
             Def::SelfTy(_, Some(impl_id)) => {
                 // Self in impl (we know the concrete type).
+
+                // For Def::SelfTy() values inlined from another crate, the
+                // impl_id will be DUMMY_NODE_ID, which would cause problems
+                // here. But we should never run into an impl from another crate
+                // in this pass.
+                assert!(impl_id != ast::DUMMY_NODE_ID);
+
                 tcx.prohibit_type_params(base_segments);
                 let ty = tcx.node_id_to_type(impl_id);
                 if let Some(free_substs) = self.get_free_substs() {
@@ -1741,33 +1750,10 @@
                 ty
             }
             hir::TyFixedLengthVec(ref ty, ref e) => {
-                let hint = UncheckedExprHint(tcx.types.usize);
-                match eval_const_expr_partial(tcx.global_tcx(), &e, hint, None) {
-                    Ok(ConstVal::Integral(ConstInt::Usize(i))) => {
-                        let i = i.as_u64(tcx.sess.target.uint_type);
-                        assert_eq!(i as usize as u64, i);
-                        tcx.mk_array(self.ast_ty_to_ty(rscope, &ty), i as usize)
-                    },
-                    Ok(val) => {
-                        span_err!(tcx.sess, ast_ty.span, E0249,
-                                  "expected usize value for array length, got {}",
-                                  val.description());
-                        self.tcx().types.err
-                    },
-                    // array length errors happen before the global constant check
-                    // so we need to report the real error
-                    Err(ConstEvalErr { kind: ErroneousReferencedConstant(box r), ..}) |
-                    Err(r) => {
-                        let mut err = struct_span_err!(tcx.sess, r.span, E0250,
-                                                       "array length constant \
-                                                        evaluation error: {}",
-                                                       r.description());
-                        if !ast_ty.span.contains(r.span) {
-                            span_note!(&mut err, ast_ty.span, "for array length here")
-                        }
-                        err.emit();
-                        self.tcx().types.err
-                    }
+                if let Ok(length) = eval_length(tcx.global_tcx(), &e, "array length") {
+                    tcx.mk_array(self.ast_ty_to_ty(rscope, &ty), length)
+                } else {
+                    self.tcx().types.err
                 }
             }
             hir::TyTypeof(ref _e) => {
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index e90b32c..aae6e3a 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -103,15 +103,6 @@
                     return;
                 }
 
-                // Check that the types of the end-points can be unified.
-                let types_unify = self.require_same_types(pat.span, rhs_ty, lhs_ty,
-                                                          "mismatched types in range");
-
-                // It's ok to return without a message as `require_same_types` prints an error.
-                if !types_unify {
-                    return;
-                }
-
                 // Now that we know the types can be unified we find the unified type and use
                 // it to type the entire expression.
                 let common_type = self.resolve_type_vars_if_possible(&lhs_ty);
@@ -120,6 +111,7 @@
 
                 // subtyping doesn't matter here, as the value is some kind of scalar
                 self.demand_eqtype(pat.span, expected, lhs_ty);
+                self.demand_eqtype(pat.span, expected, rhs_ty);
             }
             PatKind::Binding(bm, _, ref sub) => {
                 let typ = self.local_ty(pat.span, pat.id);
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index 2c7e7d2..bd2c05b 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -27,33 +27,8 @@
 /// to `trait_id` (this only cares about the trait, not the specific
 /// method that is called)
 pub fn check_legal_trait_for_method_call(ccx: &CrateCtxt, span: Span, trait_id: DefId) {
-    let tcx = ccx.tcx;
-    let did = Some(trait_id);
-    let li = &tcx.lang_items;
-
-    if did == li.drop_trait() {
-        span_err!(tcx.sess, span, E0040, "explicit use of destructor method");
-    } else if !tcx.sess.features.borrow().unboxed_closures {
-        // the #[feature(unboxed_closures)] feature isn't
-        // activated so we need to enforce the closure
-        // restrictions.
-
-        let method = if did == li.fn_trait() {
-            "call"
-        } else if did == li.fn_mut_trait() {
-            "call_mut"
-        } else if did == li.fn_once_trait() {
-            "call_once"
-        } else {
-            return // not a closure method, everything is OK.
-        };
-
-        struct_span_err!(tcx.sess, span, E0174,
-                         "explicit use of unboxed closure method `{}` is experimental",
-                         method)
-            .help("add `#![feature(unboxed_closures)]` to the crate \
-                  attributes to enable")
-            .emit();
+    if ccx.tcx.lang_items.drop_trait() == Some(trait_id) {
+        span_err!(ccx.tcx.sess, span, E0040, "explicit use of destructor method");
     }
 }
 
@@ -216,7 +191,7 @@
             _ => {
                 let mut err = self.type_error_struct(call_expr.span, |actual| {
                     format!("expected function, found `{}`", actual)
-                }, callee_ty, None);
+                }, callee_ty);
 
                 if let hir::ExprCall(ref expr, _) = call_expr.node {
                     let tcx = self.tcx;
diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs
index 22ac8bc..7a4cc09 100644
--- a/src/librustc_typeck/check/cast.rs
+++ b/src/librustc_typeck/check/cast.rs
@@ -149,7 +149,7 @@
                     format!("casting `{}` as `{}` is invalid",
                             actual,
                             fcx.ty_to_string(self.cast_ty))
-                }, self.expr_ty, None)
+                }, self.expr_ty)
                     .help(&format!("cast through {} first", match e {
                             CastError::NeedViaPtr => "a raw pointer",
                             CastError::NeedViaThinPtr => "a thin pointer",
@@ -167,35 +167,35 @@
             CastError::CastToChar => {
                 fcx.type_error_message(self.span, |actual| {
                     format!("only `u8` can be cast as `char`, not `{}`", actual)
-                }, self.expr_ty, None);
+                }, self.expr_ty);
             }
             CastError::NonScalar => {
                 fcx.type_error_message(self.span, |actual| {
                     format!("non-scalar cast: `{}` as `{}`",
                             actual,
                             fcx.ty_to_string(self.cast_ty))
-                }, self.expr_ty, None);
+                }, self.expr_ty);
             }
             CastError::IllegalCast => {
                 fcx.type_error_message(self.span, |actual| {
                     format!("casting `{}` as `{}` is invalid",
                             actual,
                             fcx.ty_to_string(self.cast_ty))
-                }, self.expr_ty, None);
+                }, self.expr_ty);
             }
             CastError::SizedUnsizedCast => {
                 fcx.type_error_message(self.span, |actual| {
                     format!("cannot cast thin pointer `{}` to fat pointer `{}`",
                             actual,
                             fcx.ty_to_string(self.cast_ty))
-                }, self.expr_ty, None)
+                }, self.expr_ty)
             }
             CastError::DifferingKinds => {
                 fcx.type_error_struct(self.span, |actual| {
                     format!("casting `{}` as `{}` is invalid",
                             actual,
                             fcx.ty_to_string(self.cast_ty))
-                }, self.expr_ty, None)
+                }, self.expr_ty)
                     .note("vtable kinds may not match")
                     .emit();
             }
@@ -213,7 +213,7 @@
         let tstr = fcx.ty_to_string(self.cast_ty);
         let mut err = fcx.type_error_struct(self.span, |actual| {
             format!("cast to unsized type: `{}` as `{}`", actual, tstr)
-        }, self.expr_ty, None);
+        }, self.expr_ty);
         match self.expr_ty.sty {
             ty::TyRef(_, ty::TypeAndMut { mutbl: mt, .. }) => {
                 let mtstr = match mt {
@@ -484,4 +484,3 @@
         traits::type_known_to_meet_builtin_bound(self, ty, ty::BoundSized, span)
     }
 }
-
diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs
index 35a5bc9..9844377 100644
--- a/src/librustc_typeck/check/compare_method.rs
+++ b/src/librustc_typeck/check/compare_method.rs
@@ -12,6 +12,7 @@
 use rustc::infer::{self, InferOk, TypeOrigin};
 use rustc::ty;
 use rustc::traits::{self, ProjectionMode};
+use rustc::ty::error::ExpectedFound;
 use rustc::ty::subst::{self, Subst, Substs, VecPerParamSpace};
 
 use syntax::ast;
@@ -324,10 +325,19 @@
             debug!("sub_types failed: impl ty {:?}, trait ty {:?}",
                    impl_fty,
                    trait_fty);
-            span_err!(tcx.sess, impl_m_span, E0053,
-                      "method `{}` has an incompatible type for trait: {}",
-                      trait_m.name,
-                      terr);
+
+            let mut diag = struct_span_err!(
+                tcx.sess, origin.span(), E0053,
+                "method `{}` has an incompatible type for trait", trait_m.name
+            );
+            infcx.note_type_err(
+                &mut diag, origin,
+                Some(infer::ValuePairs::Types(ExpectedFound {
+                    expected: trait_fty,
+                    found: impl_fty
+                })), &terr
+            );
+            diag.emit();
             return
         }
 
@@ -437,10 +447,9 @@
         // Compute skolemized form of impl and trait const tys.
         let impl_ty = impl_c.ty.subst(tcx, impl_to_skol_substs);
         let trait_ty = trait_c.ty.subst(tcx, &trait_to_skol_substs);
+        let origin = TypeOrigin::Misc(impl_c_span);
 
         let err = infcx.commit_if_ok(|_| {
-            let origin = TypeOrigin::Misc(impl_c_span);
-
             // There is no "body" here, so just pass dummy id.
             let impl_ty =
                 assoc::normalize_associated_types_in(&infcx,
@@ -473,11 +482,19 @@
             debug!("checking associated const for compatibility: impl ty {:?}, trait ty {:?}",
                    impl_ty,
                    trait_ty);
-            span_err!(tcx.sess, impl_c_span, E0326,
-                      "implemented const `{}` has an incompatible type for \
-                      trait: {}",
-                      trait_c.name,
-                      terr);
+            let mut diag = struct_span_err!(
+                tcx.sess, origin.span(), E0326,
+                "implemented const `{}` has an incompatible type for trait",
+                trait_c.name
+            );
+            infcx.note_type_err(
+                &mut diag, origin,
+                Some(infer::ValuePairs::Types(ExpectedFound {
+                    expected: trait_ty,
+                    found: impl_ty
+                })), &terr
+            );
+            diag.emit();
         }
     });
 }
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index eeebd6a..1f3a83e 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -33,7 +33,14 @@
     }
 
     pub fn demand_eqtype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) {
-        let origin = TypeOrigin::Misc(sp);
+        self.demand_eqtype_with_origin(TypeOrigin::Misc(sp), expected, actual);
+    }
+
+    pub fn demand_eqtype_with_origin(&self,
+                                     origin: TypeOrigin,
+                                     expected: Ty<'tcx>,
+                                     actual: Ty<'tcx>)
+    {
         match self.eq_types(false, origin, actual, expected) {
             Ok(InferOk { obligations, .. }) => {
                 // FIXME(#32730) propagate obligations
@@ -54,16 +61,4 @@
             self.report_mismatched_types(origin, expected, expr_ty, e);
         }
     }
-
-    pub fn require_same_types(&self, span: Span, t1: Ty<'tcx>, t2: Ty<'tcx>, msg: &str)
-                              -> bool {
-        if let Err(err) = self.eq_types(false, TypeOrigin::Misc(span), t1, t2) {
-            let found_ty = self.resolve_type_vars_if_possible(&t1);
-            let expected_ty = self.resolve_type_vars_if_possible(&t2);
-            ::emit_type_err(self.tcx, span, found_ty, expected_ty, &err, msg);
-            false
-        } else {
-            true
-        }
-    }
 }
diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index 5a3268e..8a53c59 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -12,6 +12,7 @@
 //! intrinsics that the compiler exposes.
 
 use intrinsics;
+use rustc::infer::TypeOrigin;
 use rustc::ty::subst::{self, Substs};
 use rustc::ty::FnSig;
 use rustc::ty::{self, Ty};
@@ -56,10 +57,9 @@
              i_n_tps, n_tps);
     } else {
         require_same_types(ccx,
-                           it.span,
+                           TypeOrigin::IntrinsicType(it.span),
                            i_ty.ty,
-                           fty,
-                           "intrinsic has wrong type");
+                           fty);
     }
 }
 
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index f20dcdc..346449d 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -160,8 +160,7 @@
                                 item_name,
                                 actual)
                     },
-                    rcvr_ty,
-                    None);
+                    rcvr_ty);
 
                 // If the item has the name of a field, give a help note
                 if let (&ty::TyStruct(def, substs), Some(expr)) = (&rcvr_ty.sty, rcvr_expr) {
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index fc1d223..6062bd0 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -126,7 +126,7 @@
 use rustc::hir::{self, PatKind};
 use rustc::hir::print as pprust;
 use rustc_back::slice;
-use rustc_const_eval::eval_repeat_count;
+use rustc_const_eval::eval_length;
 
 mod assoc;
 mod autoderef;
@@ -2541,21 +2541,21 @@
                         self.type_error_message(arg.span, |t| {
                             format!("can't pass an `{}` to variadic \
                                      function, cast to `c_double`", t)
-                        }, arg_ty, None);
+                        }, arg_ty);
                     }
                     ty::TyInt(ast::IntTy::I8) | ty::TyInt(ast::IntTy::I16) | ty::TyBool => {
                         self.type_error_message(arg.span, |t| {
                             format!("can't pass `{}` to variadic \
                                      function, cast to `c_int`",
                                            t)
-                        }, arg_ty, None);
+                        }, arg_ty);
                     }
                     ty::TyUint(ast::UintTy::U8) | ty::TyUint(ast::UintTy::U16) => {
                         self.type_error_message(arg.span, |t| {
                             format!("can't pass `{}` to variadic \
                                      function, cast to `c_uint`",
                                            t)
-                        }, arg_ty, None);
+                        }, arg_ty);
                     }
                     ty::TyFnDef(_, _, f) => {
                         let ptr_ty = self.tcx.mk_fn_ptr(f);
@@ -2564,7 +2564,7 @@
                                                 |t| {
                             format!("can't pass `{}` to variadic \
                                      function, cast to `{}`", t, ptr_ty)
-                        }, arg_ty, None);
+                        }, arg_ty);
                     }
                     _ => {}
                 }
@@ -2908,9 +2908,8 @@
             self.type_error_struct(field.span, |actual| {
                 format!("attempted to take value of method `{}` on type \
                          `{}`", field.node, actual)
-            }, expr_t, None)
-                .help(
-                       "maybe a `()` to call it is missing? \
+            }, expr_t)
+                .help("maybe a `()` to call it is missing? \
                        If not, try an anonymous function")
                 .emit();
             self.write_error(expr.id);
@@ -2919,7 +2918,7 @@
                 format!("attempted access of field `{}` on type `{}`, \
                          but no field with that name was found",
                         field.node, actual)
-            }, expr_t, None);
+            }, expr_t);
             if let ty::TyStruct(def, _) = expr_t.sty {
                 Self::suggest_field_names(&mut err, def.struct_variant(), field, vec![]);
             }
@@ -3019,7 +3018,7 @@
                                     actual)
                 }
             },
-            expr_t, None);
+            expr_t);
 
         self.write_error(expr.id);
     }
@@ -3029,17 +3028,18 @@
                             variant: ty::VariantDef<'tcx>,
                             field: &hir::Field,
                             skip_fields: &[hir::Field]) {
-        let mut err = self.type_error_struct(
+        let mut err = self.type_error_struct_with_diag(
             field.name.span,
             |actual| if let ty::TyEnum(..) = ty.sty {
-                format!("struct variant `{}::{}` has no field named `{}`",
-                        actual, variant.name.as_str(), field.name.node)
+                struct_span_err!(self.tcx.sess, field.name.span, E0559,
+                                 "struct variant `{}::{}` has no field named `{}`",
+                                 actual, variant.name.as_str(), field.name.node)
             } else {
-                format!("structure `{}` has no field named `{}`",
-                        actual, field.name.node)
+                struct_span_err!(self.tcx.sess, field.name.span, E0560,
+                                 "structure `{}` has no field named `{}`",
+                                 actual, field.name.node)
             },
-            ty,
-            None);
+            ty);
         // prevent all specified fields from being suggested
         let skip_fields = skip_fields.iter().map(|ref x| x.name.node.as_str());
         Self::suggest_field_names(&mut err, variant, &field.name, skip_fields.collect());
@@ -3272,7 +3272,7 @@
                             self.type_error_message(expr.span, |actual| {
                                 format!("type `{}` cannot be \
                                         dereferenced", actual)
-                            }, oprnd_t, None);
+                            }, oprnd_t);
                             oprnd_t = tcx.types.err;
                         }
                     }
@@ -3541,7 +3541,8 @@
           }
           hir::ExprRepeat(ref element, ref count_expr) => {
             self.check_expr_has_type(&count_expr, tcx.types.usize);
-            let count = eval_repeat_count(self.tcx.global_tcx(), &count_expr);
+            let count = eval_length(self.tcx.global_tcx(), &count_expr, "repeat count")
+                  .unwrap_or(0);
 
             let uty = match expected {
                 ExpectHasType(uty) => {
@@ -3647,8 +3648,7 @@
                                   format!("cannot index a value of type `{}`",
                                           actual)
                               },
-                              base_t,
-                              None);
+                              base_t);
                           // Try to give some advice about indexing tuples.
                           if let ty::TyTuple(_) = base_t.sty {
                               let mut needs_note = true;
@@ -4523,7 +4523,7 @@
                 if !self.is_tainted_by_errors() {
                     self.type_error_message(sp, |_actual| {
                         "the type of this value must be known in this context".to_string()
-                    }, ty, None);
+                    }, ty);
                 }
                 self.demand_suptype(sp, self.tcx.types.err, ty);
                 ty = self.tcx.types.err;
diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs
index 8604dad..d02f87d 100644
--- a/src/librustc_typeck/check/op.rs
+++ b/src/librustc_typeck/check/op.rs
@@ -239,7 +239,7 @@
                 self.type_error_message(ex.span, |actual| {
                     format!("cannot apply unary operator `{}` to type `{}`",
                             op_str, actual)
-                }, operand_ty, None);
+                }, operand_ty);
                 self.tcx.types.err
             }
         }
diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs
index 702dd5f..030491b 100644
--- a/src/librustc_typeck/check/upvar.rs
+++ b/src/librustc_typeck/check/upvar.rs
@@ -47,11 +47,11 @@
 use middle::mem_categorization::Categorization;
 use rustc::ty::{self, Ty};
 use rustc::infer::UpvarRegion;
-use std::collections::HashSet;
 use syntax::ast;
 use syntax_pos::Span;
 use rustc::hir;
 use rustc::hir::intravisit::{self, Visitor};
+use rustc::util::nodemap::NodeMap;
 
 ///////////////////////////////////////////////////////////////////////////
 // PUBLIC ENTRY POINTS
@@ -60,9 +60,8 @@
     pub fn closure_analyze_fn(&self, body: &hir::Block) {
         let mut seed = SeedBorrowKind::new(self);
         seed.visit_block(body);
-        let closures_with_inferred_kinds = seed.closures_with_inferred_kinds;
 
-        let mut adjust = AdjustBorrowKind::new(self, &closures_with_inferred_kinds);
+        let mut adjust = AdjustBorrowKind::new(self, seed.temp_closure_kinds);
         adjust.visit_block(body);
 
         // it's our job to process these.
@@ -72,9 +71,8 @@
     pub fn closure_analyze_const(&self, body: &hir::Expr) {
         let mut seed = SeedBorrowKind::new(self);
         seed.visit_expr(body);
-        let closures_with_inferred_kinds = seed.closures_with_inferred_kinds;
 
-        let mut adjust = AdjustBorrowKind::new(self, &closures_with_inferred_kinds);
+        let mut adjust = AdjustBorrowKind::new(self, seed.temp_closure_kinds);
         adjust.visit_expr(body);
 
         // it's our job to process these.
@@ -87,7 +85,7 @@
 
 struct SeedBorrowKind<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
-    closures_with_inferred_kinds: HashSet<ast::NodeId>,
+    temp_closure_kinds: NodeMap<ty::ClosureKind>,
 }
 
 impl<'a, 'gcx, 'tcx, 'v> Visitor<'v> for SeedBorrowKind<'a, 'gcx, 'tcx> {
@@ -106,7 +104,7 @@
 
 impl<'a, 'gcx, 'tcx> SeedBorrowKind<'a, 'gcx, 'tcx> {
     fn new(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>) -> SeedBorrowKind<'a, 'gcx, 'tcx> {
-        SeedBorrowKind { fcx: fcx, closures_with_inferred_kinds: HashSet::new() }
+        SeedBorrowKind { fcx: fcx, temp_closure_kinds: NodeMap() }
     }
 
     fn check_closure(&mut self,
@@ -116,11 +114,8 @@
     {
         let closure_def_id = self.fcx.tcx.map.local_def_id(expr.id);
         if !self.fcx.tables.borrow().closure_kinds.contains_key(&closure_def_id) {
-            self.closures_with_inferred_kinds.insert(expr.id);
-            self.fcx.tables.borrow_mut().closure_kinds
-                                        .insert(closure_def_id, ty::ClosureKind::Fn);
-            debug!("check_closure: adding closure_id={:?} to closures_with_inferred_kinds",
-                   closure_def_id);
+            self.temp_closure_kinds.insert(expr.id, ty::ClosureKind::Fn);
+            debug!("check_closure: adding closure {:?} as Fn", expr.id);
         }
 
         self.fcx.tcx.with_freevars(expr.id, |freevars| {
@@ -154,14 +149,14 @@
 
 struct AdjustBorrowKind<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
-    closures_with_inferred_kinds: &'a HashSet<ast::NodeId>,
+    temp_closure_kinds: NodeMap<ty::ClosureKind>,
 }
 
 impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
     fn new(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
-           closures_with_inferred_kinds: &'a HashSet<ast::NodeId>)
+           temp_closure_kinds: NodeMap<ty::ClosureKind>)
            -> AdjustBorrowKind<'a, 'gcx, 'tcx> {
-        AdjustBorrowKind { fcx: fcx, closures_with_inferred_kinds: closures_with_inferred_kinds }
+        AdjustBorrowKind { fcx: fcx, temp_closure_kinds: temp_closure_kinds }
     }
 
     fn analyze_closure(&mut self,
@@ -176,7 +171,12 @@
         debug!("analyze_closure(id={:?}, body.id={:?})", id, body.id);
 
         {
-            let mut euv = euv::ExprUseVisitor::new(self, self.fcx);
+            let mut euv =
+                euv::ExprUseVisitor::with_options(self,
+                                                  self.fcx,
+                                                  mc::MemCategorizationOptions {
+                                                      during_closure_kind_inference: true
+                                                  });
             euv.walk_fn(decl, body);
         }
 
@@ -211,10 +211,14 @@
             self.fcx.demand_eqtype(span, final_upvar_ty, upvar_ty);
         }
 
-        // Now we must process and remove any deferred resolutions,
-        // since we have a concrete closure kind.
+        // If we are also inferred the closure kind here, update the
+        // main table and process any deferred resolutions.
         let closure_def_id = self.fcx.tcx.map.local_def_id(id);
-        if self.closures_with_inferred_kinds.contains(&id) {
+        if let Some(&kind) = self.temp_closure_kinds.get(&id) {
+            self.fcx.tables.borrow_mut().closure_kinds
+                                        .insert(closure_def_id, kind);
+            debug!("closure_kind({:?}) = {:?}", closure_def_id, kind);
+
             let mut deferred_call_resolutions =
                 self.fcx.remove_deferred_call_resolutions(closure_def_id);
             for deferred_call_resolution in &mut deferred_call_resolutions {
@@ -259,7 +263,7 @@
             })
     }
 
-    fn adjust_upvar_borrow_kind_for_consume(&self,
+    fn adjust_upvar_borrow_kind_for_consume(&mut self,
                                             cmt: mc::cmt<'tcx>,
                                             mode: euv::ConsumeMode)
     {
@@ -350,7 +354,7 @@
         }
     }
 
-    fn adjust_upvar_borrow_kind_for_unique(&self, cmt: mc::cmt<'tcx>) {
+    fn adjust_upvar_borrow_kind_for_unique(&mut self, cmt: mc::cmt<'tcx>) {
         debug!("adjust_upvar_borrow_kind_for_unique(cmt={:?})",
                cmt);
 
@@ -381,7 +385,7 @@
         }
     }
 
-    fn try_adjust_upvar_deref(&self,
+    fn try_adjust_upvar_deref(&mut self,
                               note: &mc::Note,
                               borrow_kind: ty::BorrowKind)
                               -> bool
@@ -430,7 +434,7 @@
     /// moving from left to right as needed (but never right to left).
     /// Here the argument `mutbl` is the borrow_kind that is required by
     /// some particular use.
-    fn adjust_upvar_borrow_kind(&self,
+    fn adjust_upvar_borrow_kind(&mut self,
                                 upvar_id: ty::UpvarId,
                                 upvar_capture: &mut ty::UpvarCapture,
                                 kind: ty::BorrowKind) {
@@ -460,36 +464,30 @@
         }
     }
 
-    fn adjust_closure_kind(&self,
+    fn adjust_closure_kind(&mut self,
                            closure_id: ast::NodeId,
                            new_kind: ty::ClosureKind) {
         debug!("adjust_closure_kind(closure_id={}, new_kind={:?})",
                closure_id, new_kind);
 
-        if !self.closures_with_inferred_kinds.contains(&closure_id) {
-            return;
-        }
+        if let Some(&existing_kind) = self.temp_closure_kinds.get(&closure_id) {
+            debug!("adjust_closure_kind: closure_id={}, existing_kind={:?}, new_kind={:?}",
+                   closure_id, existing_kind, new_kind);
 
-        let closure_def_id = self.fcx.tcx.map.local_def_id(closure_id);
-        let closure_kinds = &mut self.fcx.tables.borrow_mut().closure_kinds;
-        let existing_kind = *closure_kinds.get(&closure_def_id).unwrap();
+            match (existing_kind, new_kind) {
+                (ty::ClosureKind::Fn, ty::ClosureKind::Fn) |
+                (ty::ClosureKind::FnMut, ty::ClosureKind::Fn) |
+                (ty::ClosureKind::FnMut, ty::ClosureKind::FnMut) |
+                (ty::ClosureKind::FnOnce, _) => {
+                    // no change needed
+                }
 
-        debug!("adjust_closure_kind: closure_id={}, existing_kind={:?}, new_kind={:?}",
-               closure_id, existing_kind, new_kind);
-
-        match (existing_kind, new_kind) {
-            (ty::ClosureKind::Fn, ty::ClosureKind::Fn) |
-            (ty::ClosureKind::FnMut, ty::ClosureKind::Fn) |
-            (ty::ClosureKind::FnMut, ty::ClosureKind::FnMut) |
-            (ty::ClosureKind::FnOnce, _) => {
-                // no change needed
-            }
-
-            (ty::ClosureKind::Fn, ty::ClosureKind::FnMut) |
-            (ty::ClosureKind::Fn, ty::ClosureKind::FnOnce) |
-            (ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
-                // new kind is stronger than the old kind
-                closure_kinds.insert(closure_def_id, new_kind);
+                (ty::ClosureKind::Fn, ty::ClosureKind::FnMut) |
+                (ty::ClosureKind::Fn, ty::ClosureKind::FnOnce) |
+                (ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
+                    // new kind is stronger than the old kind
+                    self.temp_closure_kinds.insert(closure_id, new_kind);
+                }
             }
         }
     }
@@ -503,7 +501,7 @@
                 span: Span,
                 id: ast::NodeId)
     {
-        intravisit::walk_fn(self, fn_kind, decl, body, span);
+        intravisit::walk_fn(self, fn_kind, decl, body, span, id);
         self.analyze_closure(id, span, decl, body);
     }
 }
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index d101381..34a91b2 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -13,6 +13,7 @@
 use CrateCtxt;
 use hir::def_id::DefId;
 use middle::region::{CodeExtent};
+use rustc::infer::TypeOrigin;
 use rustc::ty::subst::{self, TypeSpace, FnSpace, ParamSpace, SelfSpace};
 use rustc::traits;
 use rustc::ty::{self, Ty, TyCtxt};
@@ -157,7 +158,10 @@
         }
     }
 
-    fn check_trait_or_impl_item(&mut self, item_id: ast::NodeId, span: Span) {
+    fn check_trait_or_impl_item(&mut self,
+                                item_id: ast::NodeId,
+                                span: Span,
+                                sig_if_method: Option<&hir::MethodSig>) {
         let code = self.code.clone();
         self.for_id(item_id, span).with_fcx(|fcx, this| {
             let free_substs = &fcx.parameter_environment.free_substs;
@@ -182,7 +186,8 @@
                     let predicates = fcx.instantiate_bounds(span, free_substs, &method.predicates);
                     this.check_fn_or_method(fcx, span, &method_ty, &predicates,
                                             free_id_outlive, &mut implied_bounds);
-                    this.check_method_receiver(fcx, span, &method,
+                    let sig_if_method = sig_if_method.expect("bad signature for method");
+                    this.check_method_receiver(fcx, sig_if_method, &method,
                                                free_id_outlive, self_ty);
                 }
                 ty::TypeTraitItem(assoc_type) => {
@@ -405,20 +410,15 @@
 
     fn check_method_receiver<'fcx, 'tcx>(&mut self,
                                          fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
-                                         span: Span,
+                                         method_sig: &hir::MethodSig,
                                          method: &ty::Method<'tcx>,
                                          free_id_outlive: CodeExtent,
                                          self_ty: ty::Ty<'tcx>)
     {
         // check that the type of the method's receiver matches the
         // method's first parameter.
-
-        let free_substs = &fcx.parameter_environment.free_substs;
-        let fty = fcx.instantiate_type_scheme(span, free_substs, &method.fty);
-        let sig = fcx.tcx.liberate_late_bound_regions(free_id_outlive, &fty.sig);
-
-        debug!("check_method_receiver({:?},cat={:?},self_ty={:?},sig={:?})",
-               method.name, method.explicit_self, self_ty, sig);
+        debug!("check_method_receiver({:?},cat={:?},self_ty={:?})",
+               method.name, method.explicit_self, self_ty);
 
         let rcvr_ty = match method.explicit_self {
             ty::ExplicitSelfCategory::Static => return,
@@ -431,20 +431,34 @@
             }
             ty::ExplicitSelfCategory::ByBox => fcx.tcx.mk_box(self_ty)
         };
+
+        let span = method_sig.decl.inputs[0].pat.span;
+
+        let free_substs = &fcx.parameter_environment.free_substs;
+        let fty = fcx.instantiate_type_scheme(span, free_substs, &method.fty);
+        let sig = fcx.tcx.liberate_late_bound_regions(free_id_outlive, &fty.sig);
+
+        debug!("check_method_receiver: sig={:?}", sig);
+
         let rcvr_ty = fcx.instantiate_type_scheme(span, free_substs, &rcvr_ty);
         let rcvr_ty = fcx.tcx.liberate_late_bound_regions(free_id_outlive,
                                                           &ty::Binder(rcvr_ty));
 
         debug!("check_method_receiver: receiver ty = {:?}", rcvr_ty);
 
-        fcx.require_same_types(span, sig.inputs[0], rcvr_ty,
-                               "mismatched method receiver");
+        let origin = TypeOrigin::MethodReceiver(span);
+        fcx.demand_eqtype_with_origin(origin, rcvr_ty, sig.inputs[0]);
     }
 
     fn check_variances_for_type_defn(&self,
                                      item: &hir::Item,
                                      ast_generics: &hir::Generics)
     {
+        let ty = self.tcx().node_id_to_type(item.id);
+        if self.tcx().has_error_field(ty) {
+            return;
+        }
+
         let item_def_id = self.tcx().map.local_def_id(item.id);
         let ty_predicates = self.tcx().lookup_predicates(item_def_id);
         let variances = self.tcx().item_variances(item_def_id);
@@ -553,13 +567,21 @@
 
     fn visit_trait_item(&mut self, trait_item: &'v hir::TraitItem) {
         debug!("visit_trait_item: {:?}", trait_item);
-        self.check_trait_or_impl_item(trait_item.id, trait_item.span);
+        let method_sig = match trait_item.node {
+            hir::TraitItem_::MethodTraitItem(ref sig, _) => Some(sig),
+            _ => None
+        };
+        self.check_trait_or_impl_item(trait_item.id, trait_item.span, method_sig);
         intravisit::walk_trait_item(self, trait_item)
     }
 
     fn visit_impl_item(&mut self, impl_item: &'v hir::ImplItem) {
         debug!("visit_impl_item: {:?}", impl_item);
-        self.check_trait_or_impl_item(impl_item.id, impl_item.span);
+        let method_sig = match impl_item.node {
+            hir::ImplItemKind::Method(ref sig, _) => Some(sig),
+            _ => None
+        };
+        self.check_trait_or_impl_item(impl_item.id, impl_item.span, method_sig);
         intravisit::walk_impl_item(self, impl_item)
     }
 }
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 41e7a46..4486748 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -60,14 +60,11 @@
 
 use astconv::{AstConv, ast_region_to_region, Bounds, PartitionedBounds, partition_bounds};
 use lint;
-use hir::def::Def;
-use hir::def_id::DefId;
 use constrained_type_params as ctp;
 use middle::lang_items::SizedTraitLangItem;
 use middle::const_val::ConstVal;
 use rustc_const_eval::EvalHint::UncheckedExprHint;
-use rustc_const_eval::{eval_const_expr_partial, ConstEvalErr};
-use rustc_const_eval::ErrKind::ErroneousReferencedConstant;
+use rustc_const_eval::{eval_const_expr_partial, report_const_eval_err};
 use rustc::ty::subst::{Substs, FnSpace, ParamSpace, SelfSpace, TypeSpace, VecPerParamSpace};
 use rustc::ty::{ToPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer};
 use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeScheme};
@@ -75,7 +72,6 @@
 use rustc::ty::util::IntTypeExt;
 use rscope::*;
 use rustc::dep_graph::DepNode;
-use rustc::hir::map as hir_map;
 use util::common::{ErrorReported, MemoizationMap};
 use util::nodemap::{NodeMap, FnvHashMap};
 use {CrateCtxt, write_ty_to_tcx};
@@ -92,9 +88,9 @@
 use syntax::ptr::P;
 use syntax_pos::Span;
 
-use rustc::hir::{self, PatKind};
-use rustc::hir::intravisit;
-use rustc::hir::print as pprust;
+use rustc::hir::{self, intravisit, map as hir_map, print as pprust};
+use rustc::hir::def::Def;
+use rustc::hir::def_id::DefId;
 
 ///////////////////////////////////////////////////////////////////////////
 // Main entry point
@@ -1091,14 +1087,9 @@
             },
             // enum variant evaluation happens before the global constant check
             // so we need to report the real error
-            Err(ConstEvalErr { kind: ErroneousReferencedConstant(box err), ..}) |
             Err(err) => {
-                let mut diag = struct_span_err!(ccx.tcx.sess, err.span, E0080,
-                                                "constant evaluation error: {}",
-                                                err.description());
-                if !e.span.contains(err.span) {
-                    diag.span_note(e.span, "for enum discriminant here");
-                }
+                let mut diag = report_const_eval_err(
+                    ccx.tcx, &err, e.span, "enum discriminant");
                 diag.emit();
                 None
             }
@@ -2150,14 +2141,6 @@
     abi: abi::Abi)
     -> ty::TypeScheme<'tcx>
 {
-    for i in &decl.inputs {
-        match i.pat.node {
-            PatKind::Binding(..) | PatKind::Wild => {}
-            _ => span_err!(ccx.tcx.sess, i.pat.span, E0130,
-                           "patterns aren't allowed in foreign function declarations")
-        }
-    }
-
     let ty_generics = ty_generics_for_fn(ccx, ast_generics, &ty::Generics::empty());
 
     let rb = BindingRscope::new();
@@ -2243,9 +2226,9 @@
     // reachable from there, to start (if this is an inherent impl,
     // then just examine the self type).
     let mut input_parameters: HashSet<_> =
-        ctp::parameters_for_type(impl_scheme.ty, false).into_iter().collect();
+        ctp::parameters_for(&impl_scheme.ty, false).into_iter().collect();
     if let Some(ref trait_ref) = impl_trait_ref {
-        input_parameters.extend(ctp::parameters_for_trait_ref(trait_ref, false));
+        input_parameters.extend(ctp::parameters_for(trait_ref, false));
     }
 
     ctp::setup_constraining_predicates(impl_predicates.predicates.get_mut_slice(TypeSpace),
@@ -2273,9 +2256,9 @@
     let impl_trait_ref = ccx.tcx.impl_trait_ref(impl_def_id);
 
     let mut input_parameters: HashSet<_> =
-        ctp::parameters_for_type(impl_scheme.ty, false).into_iter().collect();
+        ctp::parameters_for(&impl_scheme.ty, false).into_iter().collect();
     if let Some(ref trait_ref) = impl_trait_ref {
-        input_parameters.extend(ctp::parameters_for_trait_ref(trait_ref, false));
+        input_parameters.extend(ctp::parameters_for(trait_ref, false));
     }
     ctp::identify_constrained_type_params(
         &impl_predicates.predicates.as_slice(), impl_trait_ref, &mut input_parameters);
@@ -2286,7 +2269,7 @@
             ty::TypeTraitItem(ref assoc_ty) => assoc_ty.ty,
             ty::ConstTraitItem(..) | ty::MethodTraitItem(..) => None
         })
-        .flat_map(|ty| ctp::parameters_for_type(ty, true))
+        .flat_map(|ty| ctp::parameters_for(&ty, true))
         .filter_map(|p| match p {
             ctp::Parameter::Type(_) => None,
             ctp::Parameter::Region(r) => Some(r),
diff --git a/src/librustc_typeck/constrained_type_params.rs b/src/librustc_typeck/constrained_type_params.rs
index 08c1b5f..7909584 100644
--- a/src/librustc_typeck/constrained_type_params.rs
+++ b/src/librustc_typeck/constrained_type_params.rs
@@ -8,8 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use rustc::ty::{self, subst, Ty};
-
+use rustc::ty::{self, Ty};
+use rustc::ty::fold::{TypeFoldable, TypeVisitor};
 use std::collections::HashSet;
 
 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
@@ -19,77 +19,53 @@
 }
 
 /// If `include_projections` is false, returns the list of parameters that are
-/// constrained by the type `ty` - i.e. the value of each parameter in the list is
-/// uniquely determined by `ty` (see RFC 447). If it is true, return the list
+/// constrained by `t` - i.e. the value of each parameter in the list is
+/// uniquely determined by `t` (see RFC 447). If it is true, return the list
 /// of parameters whose values are needed in order to constrain `ty` - these
 /// differ, with the latter being a superset, in the presence of projections.
-pub fn parameters_for_type<'tcx>(ty: Ty<'tcx>,
-                                 include_projections: bool) -> Vec<Parameter> {
-    let mut result = vec![];
-    ty.maybe_walk(|t| match t.sty {
-        ty::TyProjection(..) if !include_projections => {
+pub fn parameters_for<'tcx, T>(t: &T,
+                               include_nonconstraining: bool)
+                               -> Vec<Parameter>
+    where T: TypeFoldable<'tcx>
+{
 
-            false // projections are not injective.
-        }
-        _ => {
-            result.append(&mut parameters_for_type_shallow(t));
-            // non-projection type constructors are injective.
-            true
-        }
-    });
-    result
+    let mut collector = ParameterCollector {
+        parameters: vec![],
+        include_nonconstraining: include_nonconstraining
+    };
+    t.visit_with(&mut collector);
+    collector.parameters
 }
 
-pub fn parameters_for_trait_ref<'tcx>(trait_ref: &ty::TraitRef<'tcx>,
-                                      include_projections: bool) -> Vec<Parameter> {
-    let mut region_parameters =
-        parameters_for_regions_in_substs(&trait_ref.substs);
-
-    let type_parameters =
-        trait_ref.substs
-                 .types
-                 .iter()
-                 .flat_map(|ty| parameters_for_type(ty, include_projections));
-
-    region_parameters.extend(type_parameters);
-
-    region_parameters
+struct ParameterCollector {
+    parameters: Vec<Parameter>,
+    include_nonconstraining: bool
 }
 
-fn parameters_for_type_shallow<'tcx>(ty: Ty<'tcx>) -> Vec<Parameter> {
-    match ty.sty {
-        ty::TyParam(ref d) =>
-            vec![Parameter::Type(d.clone())],
-        ty::TyRef(region, _) =>
-            parameters_for_region(region).into_iter().collect(),
-        ty::TyStruct(_, substs) |
-        ty::TyEnum(_, substs) =>
-            parameters_for_regions_in_substs(substs),
-        ty::TyTrait(ref data) =>
-            parameters_for_regions_in_substs(&data.principal.skip_binder().substs),
-        ty::TyProjection(ref pi) =>
-            parameters_for_regions_in_substs(&pi.trait_ref.substs),
-        ty::TyBool | ty::TyChar | ty::TyInt(..) | ty::TyUint(..) |
-        ty::TyFloat(..) | ty::TyBox(..) | ty::TyStr |
-        ty::TyArray(..) | ty::TySlice(..) |
-        ty::TyFnDef(..) | ty::TyFnPtr(_) |
-        ty::TyTuple(..) | ty::TyRawPtr(..) |
-        ty::TyInfer(..) | ty::TyClosure(..) | ty::TyError =>
-            vec![]
+impl<'tcx> TypeVisitor<'tcx> for ParameterCollector {
+    fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
+        match t.sty {
+            ty::TyProjection(..) if !self.include_nonconstraining => {
+                // projections are not injective
+                return false;
+            }
+            ty::TyParam(ref d) => {
+                self.parameters.push(Parameter::Type(d.clone()));
+            }
+            _ => {}
+        }
+
+        t.super_visit_with(self)
     }
-}
 
-fn parameters_for_regions_in_substs(substs: &subst::Substs) -> Vec<Parameter> {
-    substs.regions
-          .iter()
-          .filter_map(|r| parameters_for_region(r))
-          .collect()
-}
-
-fn parameters_for_region(region: &ty::Region) -> Option<Parameter> {
-    match *region {
-        ty::ReEarlyBound(data) => Some(Parameter::Region(data)),
-        _ => None,
+    fn visit_region(&mut self, r: ty::Region) -> bool {
+        match r {
+            ty::ReEarlyBound(data) => {
+                self.parameters.push(Parameter::Region(data));
+            }
+            _ => {}
+        }
+        false
     }
 }
 
@@ -191,12 +167,12 @@
                 // Then the projection only applies if `T` is known, but it still
                 // does not determine `U`.
 
-                let inputs = parameters_for_trait_ref(&projection.projection_ty.trait_ref, true);
+                let inputs = parameters_for(&projection.projection_ty.trait_ref, true);
                 let relies_only_on_inputs = inputs.iter().all(|p| input_parameters.contains(&p));
                 if !relies_only_on_inputs {
                     continue;
                 }
-                input_parameters.extend(parameters_for_type(projection.ty, false));
+                input_parameters.extend(parameters_for(&projection.ty, false));
             } else {
                 continue;
             }
diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs
index 8769bc1..b655d95 100644
--- a/src/librustc_typeck/diagnostics.rs
+++ b/src/librustc_typeck/diagnostics.rs
@@ -1079,25 +1079,6 @@
 ```
 "##,
 
-E0080: r##"
-This error indicates that the compiler was unable to sensibly evaluate an
-integer expression provided as an enum discriminant. Attempting to divide by 0
-or causing integer overflow are two ways to induce this error. For example:
-
-```compile_fail
-enum Enum {
-    X = (1 << 500),
-    Y = (1 / 0)
-}
-```
-
-Ensure that the expressions given can be evaluated as the desired integer type.
-See the FFI section of the Reference for more information about using a custom
-integer type:
-
-https://doc.rust-lang.org/reference.html#ffi-attributes
-"##,
-
 E0081: r##"
 Enum discriminants are used to differentiate enum variants stored in memory.
 This error indicates that the same value was used for two or more variants,
@@ -1819,39 +1800,6 @@
 parameter if so.
 "##,
 
-E0130: r##"
-You declared a pattern as an argument in a foreign function declaration.
-Erroneous code example:
-
-```compile_fail
-extern {
-    fn foo((a, b): (u32, u32)); // error: patterns aren't allowed in foreign
-                                //        function declarations
-}
-```
-
-Please replace the pattern argument with a regular one. Example:
-
-```
-struct SomeStruct {
-    a: u32,
-    b: u32,
-}
-
-extern {
-    fn foo(s: SomeStruct); // ok!
-}
-```
-
-Or:
-
-```
-extern {
-    fn foo(a: (u32, u32)); // ok!
-}
-```
-"##,
-
 E0131: r##"
 It is not possible to define `main` with type parameters, or even with function
 parameters. When `main` is present, it must take no arguments and return `()`.
@@ -1963,89 +1911,6 @@
 https://doc.rust-lang.org/book/traits.html
 "##,
 
-E0174: r##"
-This error occurs because of the explicit use of unboxed closure methods
-that are an experimental feature in current Rust version.
-
-Example of erroneous code:
-
-```compile_fail
-fn foo<F: Fn(&str)>(mut f: F) {
-    f.call(("call",));
-    // error: explicit use of unboxed closure method `call`
-    f.call_mut(("call_mut",));
-    // error: explicit use of unboxed closure method `call_mut`
-    f.call_once(("call_once",));
-    // error: explicit use of unboxed closure method `call_once`
-}
-
-fn bar(text: &str) {
-    println!("Calling {} it works!", text);
-}
-
-fn main() {
-    foo(bar);
-}
-```
-
-Rust's implementation of closures is a bit different than other languages.
-They are effectively syntax sugar for traits `Fn`, `FnMut` and `FnOnce`.
-To understand better how the closures are implemented see here:
-https://doc.rust-lang.org/book/closures.html#closure-implementation
-
-To fix this you can call them using parenthesis, like this: `foo()`.
-When you execute the closure with parenthesis, under the hood you are executing
-the method `call`, `call_mut` or `call_once`. However, using them explicitly is
-currently an experimental feature.
-
-Example of an implicit call:
-
-```
-fn foo<F: Fn(&str)>(f: F) {
-    f("using ()"); // Calling using () it works!
-}
-
-fn bar(text: &str) {
-    println!("Calling {} it works!", text);
-}
-
-fn main() {
-    foo(bar);
-}
-```
-
-To enable the explicit calls you need to add `#![feature(unboxed_closures)]`.
-
-This feature is still unstable so you will also need to add
-`#![feature(fn_traits)]`.
-More details about this issue here:
-https://github.com/rust-lang/rust/issues/29625
-
-Example of use:
-
-```
-#![feature(fn_traits)]
-#![feature(unboxed_closures)]
-
-fn foo<F: Fn(&str)>(mut f: F) {
-    f.call(("call",)); // Calling 'call' it works!
-    f.call_mut(("call_mut",)); // Calling 'call_mut' it works!
-    f.call_once(("call_once",)); // Calling 'call_once' it works!
-}
-
-fn bar(text: &str) {
-    println!("Calling '{}' it works!", text);
-}
-
-fn main() {
-    foo(bar);
-}
-```
-
-To see more about closures take a look here:
-https://doc.rust-lang.org/book/closures.html`
-"##,
-
 E0178: r##"
 In types, the `+` type operator has low precedence, so it is often necessary
 to use parentheses.
@@ -2660,6 +2525,7 @@
 [RFC 1023]: https://github.com/rust-lang/rfcs/pull/1023
 "##,
 
+/*
 E0211: r##"
 You used a function or type which doesn't fit the requirements for where it was
 used. Erroneous code examples:
@@ -2739,6 +2605,7 @@
 }
 ```
 "##,
+     */
 
 E0214: r##"
 A generic type was described using parentheses rather than angle brackets. For
@@ -2968,38 +2835,6 @@
 behavior for specific enum variants.
 "##,
 
-E0249: r##"
-This error indicates a constant expression for the array length was found, but
-it was not an integer (signed or unsigned) expression.
-
-Some examples of code that produces this error are:
-
-```compile_fail
-const A: [u32; "hello"] = []; // error
-const B: [u32; true] = []; // error
-const C: [u32; 0.0] = []; // error
-"##,
-
-E0250: r##"
-There was an error while evaluating the expression for the length of a fixed-
-size array type.
-
-Some examples of this error are:
-
-```compile_fail
-// divide by zero in the length expression
-const A: [u32; 1/0] = [];
-
-// Rust currently will not evaluate the function `foo` at compile time
-fn foo() -> usize { 12 }
-const B: [u32; foo()] = [];
-
-// it is an error to try to add `u8` and `f64`
-use std::{f64, u8};
-const C: [u32; u8::MAX + f64::EPSILON] = [];
-```
-"##,
-
 E0318: r##"
 Default impls for a trait must be located in the same crate where the trait was
 defined. For more information see the [opt-in builtin traits RFC](https://github
@@ -4029,6 +3864,57 @@
 ```
 "##,
 
+E0559: r##"
+An unknown field was specified into an enum's structure variant.
+
+Erroneous code example:
+
+```compile_fail,E0559
+enum Field {
+    Fool { x: u32 },
+}
+
+let s = Field::Fool { joke: 0 };
+// error: struct variant `Field::Fool` has no field named `joke`
+```
+
+Verify you didn't misspell the field's name or that the field exists. Example:
+
+```
+enum Field {
+    Fool { joke: u32 },
+}
+
+let s = Field::Fool { joke: 0 }; // ok!
+```
+"##,
+
+E0560: r##"
+An unknown field was specified into a structure.
+
+Erroneous code example:
+
+```compile_fail,E0560
+struct Simba {
+    mother: u32,
+}
+
+let s = Simba { mother: 1, father: 0 };
+// error: structure `Simba` has no field named `father`
+```
+
+Verify you didn't misspell the field's name or that the field exists. Example:
+
+```
+struct Simba {
+    mother: u32,
+    father: u32,
+}
+
+let s = Simba { mother: 1, father: 0 }; // ok!
+```
+"##,
+
 }
 
 register_diagnostics! {
@@ -4047,6 +3933,7 @@
     E0167,
 //  E0168,
 //  E0173, // manual implementations of unboxed closure traits are experimental
+//  E0174,
     E0182,
     E0183,
 //  E0187, // can't infer the kind of the closure
@@ -4086,6 +3973,7 @@
     E0245, // not a trait
 //  E0246, // invalid recursive type
 //  E0247,
+//  E0249,
 //  E0319, // trait impls for defaulted traits allowed just for structs/enums
     E0320, // recursive overflow during dropck
     E0328, // cannot implement Unsize explicitly
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index 8445258..3b2d02d 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -186,28 +186,14 @@
     }
 }
 
-pub fn emit_type_err<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                                     span: Span,
-                                     found_ty: Ty<'tcx>,
-                                     expected_ty: Ty<'tcx>,
-                                     terr: &ty::error::TypeError<'tcx>,
-                                     msg: &str) {
-    let mut err = struct_span_err!(tcx.sess, span, E0211, "{}", msg);
-    err.span_label(span, &terr);
-    err.note_expected_found(&"type", &expected_ty, &found_ty);
-    tcx.note_and_explain_type_err(&mut err, terr, span);
-    err.emit();
-}
-
 fn require_same_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
-                                span: Span,
+                                origin: TypeOrigin,
                                 t1: Ty<'tcx>,
-                                t2: Ty<'tcx>,
-                                msg: &str)
+                                t2: Ty<'tcx>)
                                 -> bool {
     ccx.tcx.infer_ctxt(None, None, ProjectionMode::AnyFinal).enter(|infcx| {
-        if let Err(err) = infcx.eq_types(false, TypeOrigin::Misc(span), t1, t2) {
-            emit_type_err(infcx.tcx, span, t1, t2, &err, msg);
+        if let Err(err) = infcx.eq_types(false, origin.clone(), t1, t2) {
+            infcx.report_mismatched_types(origin, t1, t2, err);
             false
         } else {
             true
@@ -249,8 +235,11 @@
                 })
             }));
 
-            require_same_types(ccx, main_span, main_t, se_ty,
-                               "main function has wrong type");
+            require_same_types(
+                ccx,
+                TypeOrigin::MainFunctionType(main_span),
+                main_t,
+                se_ty);
         }
         _ => {
             span_bug!(main_span,
@@ -298,8 +287,11 @@
                 }),
             }));
 
-            require_same_types(ccx, start_span, start_t, se_ty,
-                               "start function has wrong type");
+            require_same_types(
+                ccx,
+                TypeOrigin::StartFunctionType(start_span),
+                start_t,
+                se_ty);
         }
         _ => {
             span_bug!(start_span,
diff --git a/src/librustc_unicode/char.rs b/src/librustc_unicode/char.rs
index 1ea0f8d..81856cb 100644
--- a/src/librustc_unicode/char.rs
+++ b/src/librustc_unicode/char.rs
@@ -36,7 +36,7 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::char::{MAX, from_digit, from_u32, from_u32_unchecked};
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use core::char::{EncodeUtf16, EncodeUtf8, EscapeDefault, EscapeUnicode};
+pub use core::char::{EncodeUtf16, EncodeUtf8, EscapeDebug, EscapeDefault, EscapeUnicode};
 
 // unstable reexports
 #[unstable(feature = "decode_utf8", issue = "33906")]
@@ -269,6 +269,41 @@
 
     /// Returns an iterator that yields the literal escape code of a `char`.
     ///
+    /// This will escape the characters similar to the `Debug` implementations
+    /// of `str` or `char`.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// for i in '\n'.escape_default() {
+    ///     println!("{}", i);
+    /// }
+    /// ```
+    ///
+    /// This prints:
+    ///
+    /// ```text
+    /// \
+    /// n
+    /// ```
+    ///
+    /// Collecting into a `String`:
+    ///
+    /// ```
+    /// let quote: String = '\n'.escape_default().collect();
+    ///
+    /// assert_eq!(quote, "\\n");
+    /// ```
+    #[unstable(feature = "char_escape_debug", issue = "35068")]
+    #[inline]
+    pub fn escape_debug(self) -> EscapeDebug {
+        C::escape_debug(self)
+    }
+
+    /// Returns an iterator that yields the literal escape code of a `char`.
+    ///
     /// The default is chosen with a bias toward producing literals that are
     /// legal in a variety of languages, including C++11 and similar C-family
     /// languages. The exact rules are:
diff --git a/src/librustc_unicode/lib.rs b/src/librustc_unicode/lib.rs
index f91a754..3ae905e 100644
--- a/src/librustc_unicode/lib.rs
+++ b/src/librustc_unicode/lib.rs
@@ -32,6 +32,7 @@
 #![cfg_attr(not(stage0), deny(warnings))]
 #![no_std]
 
+#![feature(char_escape_debug)]
 #![feature(core_char_ext)]
 #![feature(decode_utf8)]
 #![feature(lang_items)]
diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml
index a41d3b0..3e510bd 100644
--- a/src/librustdoc/Cargo.toml
+++ b/src/librustdoc/Cargo.toml
@@ -28,4 +28,4 @@
 
 [build-dependencies]
 build_helper = { path = "../build_helper" }
-gcc = "0.3"
+gcc = "0.3.27"
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 0211b2c..d609ad8 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -498,21 +498,20 @@
 
 impl Clean<Attribute> for ast::MetaItem {
     fn clean(&self, cx: &DocContext) -> Attribute {
-        match self.node {
-            ast::MetaItemKind::Word(ref s) => Word(s.to_string()),
-            ast::MetaItemKind::List(ref s, ref l) => {
-                List(s.to_string(), l.clean(cx))
-            }
-            ast::MetaItemKind::NameValue(ref s, ref v) => {
-                NameValue(s.to_string(), lit_to_string(v))
-            }
-        }
+        if self.is_word() {
+            Word(self.name().to_string())
+        } else if let Some(v) = self.value_str() {
+            NameValue(self.name().to_string(), v.to_string())
+        } else { // must be a list
+            let l = self.meta_item_list().unwrap();
+            List(self.name().to_string(), l.clean(cx))
+       }
     }
 }
 
 impl Clean<Attribute> for ast::Attribute {
     fn clean(&self, cx: &DocContext) -> Attribute {
-        self.with_desugared_doc(|a| a.node.value.clean(cx))
+        self.with_desugared_doc(|a| a.meta().clean(cx))
     }
 }
 
@@ -535,6 +534,28 @@
         }
     }
     fn meta_item_list<'a>(&'a self) -> Option<&'a [P<ast::MetaItem>]> { None }
+
+    fn is_word(&self) -> bool {
+      match *self {
+        Word(_) => true,
+        _ => false,
+      }
+    }
+
+    fn is_value_str(&self) -> bool {
+      match *self {
+        NameValue(..) => true,
+        _ => false,
+      }
+    }
+
+    fn is_meta_item_list(&self) -> bool {
+      match *self {
+        List(..) => true,
+        _ => false,
+      }
+    }
+
     fn span(&self) -> syntax_pos::Span { unimplemented!() }
 }
 
@@ -2568,26 +2589,6 @@
     }
 }
 
-fn lit_to_string(lit: &ast::Lit) -> String {
-    match lit.node {
-        ast::LitKind::Str(ref st, _) => st.to_string(),
-        ast::LitKind::ByteStr(ref data) => format!("{:?}", data),
-        ast::LitKind::Byte(b) => {
-            let mut res = String::from("b'");
-            for c in (b as char).escape_default() {
-                res.push(c);
-            }
-            res.push('\'');
-            res
-        },
-        ast::LitKind::Char(c) => format!("'{}'", c),
-        ast::LitKind::Int(i, _t) => i.to_string(),
-        ast::LitKind::Float(ref f, _t) => f.to_string(),
-        ast::LitKind::FloatUnsuffixed(ref f) => f.to_string(),
-        ast::LitKind::Bool(b) => b.to_string(),
-    }
-}
-
 fn name_from_pat(p: &hir::Pat) -> String {
     use rustc::hir::*;
     debug!("Trying to get a name from pattern: {:?}", p);
@@ -2690,7 +2691,12 @@
         Def::Static(i, _) => (i, TypeStatic),
         Def::Variant(i, _) => (i, TypeEnum),
         Def::SelfTy(Some(def_id), _) => (def_id, TypeTrait),
-        Def::SelfTy(_, Some(impl_id)) => return cx.map.local_def_id(impl_id),
+        Def::SelfTy(_, Some(impl_id)) => {
+            // For Def::SelfTy() values inlined from another crate, the
+            // impl_id will be DUMMY_NODE_ID, which would cause problems.
+            // But we should never run into an impl from another crate here.
+            return cx.map.local_def_id(impl_id)
+        }
         _ => return def.def_id()
     };
     if did.is_local() { return did }
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 2e2fc01..e4e886c 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -2409,10 +2409,13 @@
            if structhead {"struct "} else {""},
            it.name.as_ref().unwrap())?;
     if let Some(g) = g {
-        write!(w, "{}{}", *g, WhereClause(g))?
+        write!(w, "{}", g)?
     }
     match ty {
         doctree::Plain => {
+            if let Some(g) = g {
+                write!(w, "{}", WhereClause(g))?
+            }
             write!(w, " {{\n{}", tab)?;
             for field in fields {
                 if let clean::StructFieldItem(ref ty) = field.inner {
@@ -2445,9 +2448,17 @@
                     _ => unreachable!()
                 }
             }
-            write!(w, ");")?;
+            write!(w, ")")?;
+            if let Some(g) = g {
+                write!(w, "{}", WhereClause(g))?
+            }
+            write!(w, ";")?;
         }
         doctree::Unit => {
+            // Needed for PhantomData.
+            if let Some(g) = g {
+                write!(w, "{}", WhereClause(g))?
+            }
             write!(w, ";")?;
         }
     }
diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml
index eded6e2..3ce6841 100644
--- a/src/libstd/Cargo.toml
+++ b/src/libstd/Cargo.toml
@@ -24,8 +24,9 @@
 
 [build-dependencies]
 build_helper = { path = "../build_helper" }
-gcc = "0.3"
+gcc = "0.3.27"
 
 [features]
+backtrace = []
 jemalloc = ["alloc_jemalloc"]
 debug-jemalloc = ["alloc_jemalloc/debug"]
diff --git a/src/libstd/build.rs b/src/libstd/build.rs
index 9c40836..9018e48 100644
--- a/src/libstd/build.rs
+++ b/src/libstd/build.rs
@@ -25,7 +25,8 @@
 
     let target = env::var("TARGET").unwrap();
     let host = env::var("HOST").unwrap();
-    if !target.contains("apple") && !target.contains("msvc") && !target.contains("emscripten"){
+    if cfg!(feature = "backtrace") && !target.contains("apple") && !target.contains("msvc") &&
+        !target.contains("emscripten") {
         build_libbacktrace(&host, &target);
     }
 
diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs
index 48753cc..38fd935 100644
--- a/src/libstd/fs.rs
+++ b/src/libstd/fs.rs
@@ -694,6 +694,23 @@
     ///
     /// This field may not be available on all platforms, and will return an
     /// `Err` on platforms where it is not available.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # fn foo() -> std::io::Result<()> {
+    /// use std::fs;
+    ///
+    /// let metadata = try!(fs::metadata("foo.txt"));
+    ///
+    /// if let Ok(time) = metadata.modified() {
+    ///     println!("{:?}", time);
+    /// } else {
+    ///     println!("Not supported on this platform");
+    /// }
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "fs_time", since = "1.10.0")]
     pub fn modified(&self) -> io::Result<SystemTime> {
         self.0.modified().map(FromInner::from_inner)
@@ -712,6 +729,23 @@
     ///
     /// This field may not be available on all platforms, and will return an
     /// `Err` on platforms where it is not available.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # fn foo() -> std::io::Result<()> {
+    /// use std::fs;
+    ///
+    /// let metadata = try!(fs::metadata("foo.txt"));
+    ///
+    /// if let Ok(time) = metadata.accessed() {
+    ///     println!("{:?}", time);
+    /// } else {
+    ///     println!("Not supported on this platform");
+    /// }
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "fs_time", since = "1.10.0")]
     pub fn accessed(&self) -> io::Result<SystemTime> {
         self.0.accessed().map(FromInner::from_inner)
@@ -726,6 +760,23 @@
     ///
     /// This field may not be available on all platforms, and will return an
     /// `Err` on platforms where it is not available.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # fn foo() -> std::io::Result<()> {
+    /// use std::fs;
+    ///
+    /// let metadata = try!(fs::metadata("foo.txt"));
+    ///
+    /// if let Ok(time) = metadata.created() {
+    ///     println!("{:?}", time);
+    /// } else {
+    ///     println!("Not supported on this platform");
+    /// }
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "fs_time", since = "1.10.0")]
     pub fn created(&self) -> io::Result<SystemTime> {
         self.0.created().map(FromInner::from_inner)
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index d05a5a0..865d067 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -218,8 +218,9 @@
 #![feature(associated_consts)]
 #![feature(borrow_state)]
 #![feature(box_syntax)]
-#![feature(cfg_target_vendor)]
 #![feature(cfg_target_thread_local)]
+#![feature(cfg_target_vendor)]
+#![feature(char_escape_debug)]
 #![feature(char_internals)]
 #![feature(collections)]
 #![feature(collections_bound)]
@@ -229,10 +230,10 @@
 #![feature(dropck_parametricity)]
 #![feature(float_extras)]
 #![feature(float_from_str_radix)]
-#![feature(fnbox)]
 #![feature(fn_traits)]
-#![feature(heap_api)]
+#![feature(fnbox)]
 #![feature(hashmap_hasher)]
+#![feature(heap_api)]
 #![feature(inclusive_range)]
 #![feature(int_error_internals)]
 #![feature(into_cow)]
@@ -242,6 +243,7 @@
 #![feature(linkage)]
 #![feature(macro_reexport)]
 #![cfg_attr(test, feature(map_values_mut))]
+#![feature(needs_panic_runtime)]
 #![feature(num_bits_bytes)]
 #![feature(old_wrapping)]
 #![feature(on_unimplemented)]
@@ -249,10 +251,11 @@
 #![feature(optin_builtin_traits)]
 #![feature(panic_unwind)]
 #![feature(placement_in_syntax)]
+#![feature(question_mark)]
 #![feature(rand)]
 #![feature(raw)]
-#![feature(repr_simd)]
 #![feature(reflect_marker)]
+#![feature(repr_simd)]
 #![feature(rustc_attrs)]
 #![feature(shared)]
 #![feature(sip_hash_13)]
@@ -266,6 +269,7 @@
 #![feature(str_utf16)]
 #![feature(test, rustc_private)]
 #![feature(thread_local)]
+#![feature(try_from)]
 #![feature(unboxed_closures)]
 #![feature(unicode)]
 #![feature(unique)]
@@ -273,9 +277,6 @@
 #![feature(unwind_attributes)]
 #![feature(vec_push_all)]
 #![feature(zero_one)]
-#![feature(question_mark)]
-#![feature(try_from)]
-#![feature(needs_panic_runtime)]
 
 // Issue# 30592: Systematically use alloc_system during stage0 since jemalloc
 // might be unavailable or disabled
diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs
index d73e954..57a4c3d 100644
--- a/src/libstd/panicking.rs
+++ b/src/libstd/panicking.rs
@@ -28,9 +28,7 @@
 use mem;
 use raw;
 use sys_common::rwlock::RWLock;
-use sync::atomic::{AtomicBool, Ordering};
 use sys::stdio::Stderr;
-use sys_common::backtrace;
 use sys_common::thread_info;
 use sys_common::util;
 use thread;
@@ -71,7 +69,6 @@
 
 static HOOK_LOCK: RWLock = RWLock::new();
 static mut HOOK: Hook = Hook::Default;
-static FIRST_PANIC: AtomicBool = AtomicBool::new(true);
 
 /// Registers a custom panic hook, replacing any that was previously registered.
 ///
@@ -183,11 +180,17 @@
 }
 
 fn default_hook(info: &PanicInfo) {
-    let panics = PANIC_COUNT.with(|c| c.get());
+    #[cfg(any(not(cargobuild), feature = "backtrace"))]
+    use sys_common::backtrace;
 
     // If this is a double panic, make sure that we print a backtrace
     // for this panic. Otherwise only print it if logging is enabled.
-    let log_backtrace = panics >= 2 || backtrace::log_enabled();
+    #[cfg(any(not(cargobuild), feature = "backtrace"))]
+    let log_backtrace = {
+        let panics = PANIC_COUNT.with(|c| c.get());
+
+        panics >= 2 || backtrace::log_enabled()
+    };
 
     let file = info.location.file;
     let line = info.location.line;
@@ -207,10 +210,17 @@
         let _ = writeln!(err, "thread '{}' panicked at '{}', {}:{}",
                          name, msg, file, line);
 
-        if log_backtrace {
-            let _ = backtrace::write(err);
-        } else if FIRST_PANIC.compare_and_swap(true, false, Ordering::SeqCst) {
-            let _ = writeln!(err, "note: Run with `RUST_BACKTRACE=1` for a backtrace.");
+        #[cfg(any(not(cargobuild), feature = "backtrace"))]
+        {
+            use sync::atomic::{AtomicBool, Ordering};
+
+            static FIRST_PANIC: AtomicBool = AtomicBool::new(true);
+
+            if log_backtrace {
+                let _ = backtrace::write(err);
+            } else if FIRST_PANIC.compare_and_swap(true, false, Ordering::SeqCst) {
+                let _ = writeln!(err, "note: Run with `RUST_BACKTRACE=1` for a backtrace.");
+            }
         }
     };
 
diff --git a/src/libstd/sys/common/mod.rs b/src/libstd/sys/common/mod.rs
index c927988..a1f3f47 100644
--- a/src/libstd/sys/common/mod.rs
+++ b/src/libstd/sys/common/mod.rs
@@ -28,6 +28,7 @@
 
 pub mod args;
 pub mod at_exit_imp;
+#[cfg(any(not(cargobuild), feature = "backtrace"))]
 pub mod backtrace;
 pub mod condvar;
 pub mod io;
@@ -42,6 +43,7 @@
 pub mod util;
 pub mod wtf8;
 
+#[cfg(any(not(cargobuild), feature = "backtrace"))]
 #[cfg(any(all(unix, not(any(target_os = "macos", target_os = "ios", target_os = "emscripten"))),
           all(windows, target_env = "gnu")))]
 pub mod gnu;
diff --git a/src/libstd/sys/common/wtf8.rs b/src/libstd/sys/common/wtf8.rs
index 2c1a656..c1b4f8a 100644
--- a/src/libstd/sys/common/wtf8.rs
+++ b/src/libstd/sys/common/wtf8.rs
@@ -390,7 +390,7 @@
     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
         fn write_str_escaped(f: &mut fmt::Formatter, s: &str) -> fmt::Result {
             use fmt::Write;
-            for c in s.chars().flat_map(|c| c.escape_default()) {
+            for c in s.chars().flat_map(|c| c.escape_debug()) {
                 f.write_char(c)?
             }
             Ok(())
@@ -408,7 +408,7 @@
                             &self.bytes[pos .. surrogate_pos]
                         )},
                     )?;
-                    write!(formatter, "\\u{{{:X}}}", surrogate)?;
+                    write!(formatter, "\\u{{{:x}}}", surrogate)?;
                     pos = surrogate_pos + 3;
                 }
             }
@@ -1064,9 +1064,9 @@
 
     #[test]
     fn wtf8buf_show() {
-        let mut string = Wtf8Buf::from_str("a\té 💩\r");
+        let mut string = Wtf8Buf::from_str("a\té \u{7f}💩\r");
         string.push(CodePoint::from_u32(0xD800).unwrap());
-        assert_eq!(format!("{:?}", string), r#""a\t\u{e9} \u{1f4a9}\r\u{D800}""#);
+        assert_eq!(format!("{:?}", string), "\"a\\té \\u{7f}\u{1f4a9}\\r\\u{d800}\"");
     }
 
     #[test]
diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs
index 5434077..7758791 100644
--- a/src/libstd/sys/unix/ext/fs.rs
+++ b/src/libstd/sys/unix/ext/fs.rs
@@ -25,15 +25,53 @@
 pub trait PermissionsExt {
     /// Returns the underlying raw `mode_t` bits that are the standard Unix
     /// permissions for this file.
+    ///
+    /// # Examples
+    ///
+    /// ```rust,ignore
+    /// use std::fs::File;
+    /// use std::os::unix::fs::PermissionsExt;
+    ///
+    /// let f = try!(File::create("foo.txt"));
+    /// let metadata = try!(f.metadata());
+    /// let permissions = metadata.permissions();
+    ///
+    /// println!("permissions: {}", permissions.mode());
+    /// ```
     #[stable(feature = "fs_ext", since = "1.1.0")]
     fn mode(&self) -> u32;
 
     /// Sets the underlying raw bits for this set of permissions.
+    ///
+    /// # Examples
+    ///
+    /// ```rust,ignore
+    /// use std::fs::File;
+    /// use std::os::unix::fs::PermissionsExt;
+    ///
+    /// let f = try!(File::create("foo.txt"));
+    /// let metadata = try!(f.metadata());
+    /// let mut permissions = metadata.permissions();
+    ///
+    /// permissions.set_mode(0o644); // Read/write for owner and read for others.
+    /// assert_eq!(permissions.mode(), 0o644);
+    /// ```
     #[stable(feature = "fs_ext", since = "1.1.0")]
     fn set_mode(&mut self, mode: u32);
 
     /// Creates a new instance of `Permissions` from the given set of Unix
     /// permission bits.
+    ///
+    /// # Examples
+    ///
+    /// ```rust,ignore
+    /// use std::fs::Permissions;
+    /// use std::os::unix::fs::PermissionsExt;
+    ///
+    /// // Read/write for owner and read for others.
+    /// let permissions = Permissions::from_mode(0o644);
+    /// assert_eq!(permissions.mode(), 0o644);
+    /// ```
     #[stable(feature = "fs_ext", since = "1.1.0")]
     fn from_mode(mode: u32) -> Self;
 }
@@ -63,6 +101,18 @@
     /// If no `mode` is set, the default of `0o666` will be used.
     /// The operating system masks out bits with the systems `umask`, to produce
     /// the final permissions.
+    ///
+    /// # Examples
+    ///
+    /// ```rust,ignore
+    /// extern crate libc;
+    /// use std::fs::OpenOptions;
+    /// use std::os::unix::fs::OpenOptionsExt;
+    ///
+    /// let mut options = OpenOptions::new();
+    /// options.mode(0o644); // Give read/write for owner and read for others.
+    /// let file = options.open("foo.txt");
+    /// ```
     #[stable(feature = "fs_ext", since = "1.1.0")]
     fn mode(&mut self, mode: u32) -> &mut Self;
 
diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs
index f0fd42f..1c25c8f 100644
--- a/src/libstd/sys/unix/mod.rs
+++ b/src/libstd/sys/unix/mod.rs
@@ -30,6 +30,7 @@
 pub mod weak;
 
 pub mod android;
+#[cfg(any(not(cargobuild), feature = "backtrace"))]
 pub mod backtrace;
 pub mod condvar;
 pub mod ext;
diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs
index a784741..6f1b70a 100644
--- a/src/libstd/sys/unix/net.rs
+++ b/src/libstd/sys/unix/net.rs
@@ -67,7 +67,7 @@
             // this option, however, was added in 2.6.27, and we still support
             // 2.6.18 as a kernel, so if the returned error is EINVAL we
             // fallthrough to the fallback.
-            if cfg!(linux) {
+            if cfg!(target_os = "linux") {
                 match cvt(libc::socket(fam, ty | SOCK_CLOEXEC, 0)) {
                     Ok(fd) => return Ok(Socket(FileDesc::new(fd))),
                     Err(ref e) if e.raw_os_error() == Some(libc::EINVAL) => {}
@@ -87,7 +87,7 @@
             let mut fds = [0, 0];
 
             // Like above, see if we can set cloexec atomically
-            if cfg!(linux) {
+            if cfg!(target_os = "linux") {
                 match cvt(libc::socketpair(fam, ty | SOCK_CLOEXEC, 0, fds.as_mut_ptr())) {
                     Ok(_) => {
                         return Ok((Socket(FileDesc::new(fds[0])), Socket(FileDesc::new(fds[1]))));
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs
index 67f73d4..b622f68 100644
--- a/src/libsyntax/attr.rs
+++ b/src/libsyntax/attr.rs
@@ -17,8 +17,8 @@
 use ast;
 use ast::{AttrId, Attribute, Attribute_, MetaItem, MetaItemKind};
 use ast::{Expr, Item, Local, Stmt, StmtKind};
-use codemap::{spanned, dummy_spanned, Spanned};
-use syntax_pos::{Span, BytePos};
+use codemap::{respan, spanned, dummy_spanned, Spanned};
+use syntax_pos::{Span, BytePos, DUMMY_SP};
 use errors::Handler;
 use feature_gate::{Features, GatedCfg};
 use parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration};
@@ -92,6 +92,19 @@
     /// Gets a list of inner meta items from a list MetaItem type.
     fn meta_item_list(&self) -> Option<&[P<MetaItem>]>;
 
+    /// Indicates if the attribute is a Word.
+    fn is_word(&self) -> bool;
+
+    /// Indicates if the attribute is a Value String.
+    fn is_value_str(&self) -> bool {
+        self.value_str().is_some()
+    }
+
+    /// Indicates if the attribute is a Meta-Item List.
+    fn is_meta_item_list(&self) -> bool {
+        self.meta_item_list().is_some()
+    }
+
     fn span(&self) -> Span;
 }
 
@@ -108,8 +121,11 @@
         self.meta().value_str()
     }
     fn meta_item_list(&self) -> Option<&[P<MetaItem>]> {
-        self.node.value.meta_item_list()
+        self.meta().meta_item_list()
     }
+
+    fn is_word(&self) -> bool { self.meta().is_word() }
+
     fn span(&self) -> Span { self.meta().span }
 }
 
@@ -140,6 +156,14 @@
             _ => None
         }
     }
+
+    fn is_word(&self) -> bool {
+        match self.node {
+            MetaItemKind::Word(_) => true,
+            _ => false,
+        }
+    }
+
     fn span(&self) -> Span { self.span }
 }
 
@@ -150,6 +174,9 @@
     fn meta_item_list(&self) -> Option<&[P<MetaItem>]> {
         (**self).meta_item_list()
     }
+    fn is_word(&self) -> bool { (**self).is_word() }
+    fn is_value_str(&self) -> bool { (**self).is_value_str() }
+    fn is_meta_item_list(&self) -> bool { (**self).is_meta_item_list() }
     fn span(&self) -> Span { (**self).span() }
 }
 
@@ -194,22 +221,38 @@
 pub fn mk_name_value_item_str(name: InternedString, value: InternedString)
                               -> P<MetaItem> {
     let value_lit = dummy_spanned(ast::LitKind::Str(value, ast::StrStyle::Cooked));
-    mk_name_value_item(name, value_lit)
+    mk_spanned_name_value_item(DUMMY_SP, name, value_lit)
 }
 
 pub fn mk_name_value_item(name: InternedString, value: ast::Lit)
                           -> P<MetaItem> {
-    P(dummy_spanned(MetaItemKind::NameValue(name, value)))
+    mk_spanned_name_value_item(DUMMY_SP, name, value)
 }
 
 pub fn mk_list_item(name: InternedString, items: Vec<P<MetaItem>>) -> P<MetaItem> {
-    P(dummy_spanned(MetaItemKind::List(name, items)))
+    mk_spanned_list_item(DUMMY_SP, name, items)
 }
 
 pub fn mk_word_item(name: InternedString) -> P<MetaItem> {
-    P(dummy_spanned(MetaItemKind::Word(name)))
+    mk_spanned_word_item(DUMMY_SP, name)
 }
 
+pub fn mk_spanned_name_value_item(sp: Span, name: InternedString, value: ast::Lit)
+                          -> P<MetaItem> {
+    P(respan(sp, MetaItemKind::NameValue(name, value)))
+}
+
+pub fn mk_spanned_list_item(sp: Span, name: InternedString, items: Vec<P<MetaItem>>)
+                            -> P<MetaItem> {
+    P(respan(sp, MetaItemKind::List(name, items)))
+}
+
+pub fn mk_spanned_word_item(sp: Span, name: InternedString) -> P<MetaItem> {
+    P(respan(sp, MetaItemKind::Word(name)))
+}
+
+
+
 thread_local! { static NEXT_ATTR_ID: Cell<usize> = Cell::new(0) }
 
 pub fn mk_attr_id() -> AttrId {
@@ -223,21 +266,43 @@
 
 /// Returns an inner attribute with the given value.
 pub fn mk_attr_inner(id: AttrId, item: P<MetaItem>) -> Attribute {
-    dummy_spanned(Attribute_ {
-        id: id,
-        style: ast::AttrStyle::Inner,
-        value: item,
-        is_sugared_doc: false,
-    })
+    mk_spanned_attr_inner(DUMMY_SP, id, item)
 }
 
+/// Returns an innter attribute with the given value and span.
+pub fn mk_spanned_attr_inner(sp: Span, id: AttrId, item: P<MetaItem>) -> Attribute {
+    respan(sp,
+           Attribute_ {
+            id: id,
+            style: ast::AttrStyle::Inner,
+            value: item,
+            is_sugared_doc: false,
+          })
+}
+
+
 /// Returns an outer attribute with the given value.
 pub fn mk_attr_outer(id: AttrId, item: P<MetaItem>) -> Attribute {
+    mk_spanned_attr_outer(DUMMY_SP, id, item)
+}
+
+/// Returns an outer attribute with the given value and span.
+pub fn mk_spanned_attr_outer(sp: Span, id: AttrId, item: P<MetaItem>) -> Attribute {
+    respan(sp,
+           Attribute_ {
+            id: id,
+            style: ast::AttrStyle::Outer,
+            value: item,
+            is_sugared_doc: false,
+          })
+}
+
+pub fn mk_doc_attr_outer(id: AttrId, item: P<MetaItem>, is_sugared_doc: bool) -> Attribute {
     dummy_spanned(Attribute_ {
         id: id,
         style: ast::AttrStyle::Outer,
         value: item,
-        is_sugared_doc: false,
+        is_sugared_doc: is_sugared_doc,
     })
 }
 
diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs
index a8aca90..b176b8f 100644
--- a/src/libsyntax/codemap.rs
+++ b/src/libsyntax/codemap.rs
@@ -71,6 +71,23 @@
     respan(DUMMY_SP, t)
 }
 
+/// Build a span that covers the two provided spans.
+pub fn combine_spans(sp1: Span, sp2: Span) -> Span {
+    if sp1 == DUMMY_SP && sp2 == DUMMY_SP {
+        DUMMY_SP
+    } else if sp1 == DUMMY_SP {
+        sp2
+    } else if sp2 == DUMMY_SP {
+        sp1
+    } else {
+        Span {
+            lo: if sp1.lo < sp2.lo { sp1.lo } else { sp2.lo },
+            hi: if sp1.hi > sp2.hi { sp1.hi } else { sp2.hi },
+            expn_id: if sp1.expn_id == sp2.expn_id { sp1.expn_id } else { NO_EXPANSION },
+        }
+    }
+}
+
 #[derive(Clone, Hash, Debug)]
 pub struct NameAndSpan {
     /// The format with which the macro was invoked.
diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs
index ff75149..a825cf8 100644
--- a/src/libsyntax/config.rs
+++ b/src/libsyntax/config.rs
@@ -124,7 +124,7 @@
         };
 
         let err_count = sess.span_diagnostic.err_count();
-        let krate_attrs = strip_unconfigured.process_cfg_attrs(krate.attrs.clone());
+        let krate_attrs = strip_unconfigured.configure(krate.attrs.clone()).unwrap_or_default();
         features = get_features(&sess.span_diagnostic, &krate_attrs);
         if err_count < sess.span_diagnostic.err_count() {
             krate.attrs = krate_attrs.clone(); // Avoid reconfiguring malformed `cfg_attr`s
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 435241f..5d6429f 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -1135,30 +1135,19 @@
     }
 
     fn attribute(&self, sp: Span, mi: P<ast::MetaItem>) -> ast::Attribute {
-        respan(sp, ast::Attribute_ {
-            id: attr::mk_attr_id(),
-            style: ast::AttrStyle::Outer,
-            value: mi,
-            is_sugared_doc: false,
-        })
+        attr::mk_spanned_attr_outer(sp, attr::mk_attr_id(), mi)
     }
 
     fn meta_word(&self, sp: Span, w: InternedString) -> P<ast::MetaItem> {
-        P(respan(sp, ast::MetaItemKind::Word(w)))
+        attr::mk_spanned_word_item(sp, w)
     }
-    fn meta_list(&self,
-                 sp: Span,
-                 name: InternedString,
-                 mis: Vec<P<ast::MetaItem>> )
+    fn meta_list(&self, sp: Span, name: InternedString, mis: Vec<P<ast::MetaItem>>)
                  -> P<ast::MetaItem> {
-        P(respan(sp, ast::MetaItemKind::List(name, mis)))
+        attr::mk_spanned_list_item(sp, name, mis)
     }
-    fn meta_name_value(&self,
-                       sp: Span,
-                       name: InternedString,
-                       value: ast::LitKind)
+    fn meta_name_value(&self, sp: Span, name: InternedString, value: ast::LitKind)
                        -> P<ast::MetaItem> {
-        P(respan(sp, ast::MetaItemKind::NameValue(name, respan(sp, value))))
+        attr::mk_spanned_name_value_item(sp, name, respan(sp, value))
     }
 
     fn item_use(&self, sp: Span,
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 18342f2..5293d2a 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -302,9 +302,8 @@
         };
 
         if is_use {
-            match attr.node.value.node {
-                ast::MetaItemKind::Word(..) => (),
-                _ => fld.cx.span_err(attr.span, "arguments to macro_use are not allowed here"),
+            if !attr.is_word() {
+              fld.cx.span_err(attr.span, "arguments to macro_use are not allowed here");
             }
             return true;
         }
diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs
index 7c0d106..29a300b 100644
--- a/src/libsyntax/ext/tt/transcribe.rs
+++ b/src/libsyntax/ext/tt/transcribe.rs
@@ -14,7 +14,7 @@
 use errors::{Handler, DiagnosticBuilder};
 use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal};
 use parse::token::{DocComment, MatchNt, SubstNt};
-use parse::token::{Token, NtIdent, SpecialMacroVar};
+use parse::token::{Token, Interpolated, NtIdent, NtTT, SpecialMacroVar};
 use parse::token;
 use parse::lexer::TokenAndSpan;
 use tokenstream::{self, TokenTree};
@@ -278,9 +278,9 @@
             }
             // FIXME #2887: think about span stuff here
             TokenTree::Token(sp, SubstNt(ident)) => {
-                r.stack.last_mut().unwrap().idx += 1;
                 match lookup_cur_matched(r, ident) {
                     None => {
+                        r.stack.last_mut().unwrap().idx += 1;
                         r.cur_span = sp;
                         r.cur_tok = SubstNt(ident);
                         return ret_val;
@@ -292,14 +292,24 @@
                             // (a) idents can be in lots of places, so it'd be a pain
                             // (b) we actually can, since it's a token.
                             MatchedNonterminal(NtIdent(ref sn)) => {
+                                r.stack.last_mut().unwrap().idx += 1;
                                 r.cur_span = sn.span;
                                 r.cur_tok = token::Ident(sn.node);
                                 return ret_val;
                             }
+                            MatchedNonterminal(NtTT(ref tt)) => {
+                                r.stack.push(TtFrame {
+                                    forest: TokenTree::Token(sp, Interpolated(NtTT(tt.clone()))),
+                                    idx: 0,
+                                    dotdotdoted: false,
+                                    sep: None,
+                                });
+                            }
                             MatchedNonterminal(ref other_whole_nt) => {
+                                r.stack.last_mut().unwrap().idx += 1;
                                 // FIXME(pcwalton): Bad copy.
                                 r.cur_span = sp;
-                                r.cur_tok = token::Interpolated((*other_whole_nt).clone());
+                                r.cur_tok = Interpolated((*other_whole_nt).clone());
                                 return ret_val;
                             }
                             MatchedSeq(..) => {
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 27485ee..29da0fb 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -481,6 +481,16 @@
                                         is just used for rustc unit tests \
                                         and will never be stable",
                                        cfg_fn!(rustc_attrs))),
+    ("rustc_partition_reused", Whitelisted, Gated("rustc_attrs",
+                                                  "this attribute \
+                                                   is just used for rustc unit tests \
+                                                   and will never be stable",
+                                                  cfg_fn!(rustc_attrs))),
+    ("rustc_partition_translated", Whitelisted, Gated("rustc_attrs",
+                                                      "this attribute \
+                                                       is just used for rustc unit tests \
+                                                       and will never be stable",
+                                                      cfg_fn!(rustc_attrs))),
     ("rustc_symbol_name", Whitelisted, Gated("rustc_attrs",
                                              "internal rustc attributes will never be stable",
                                              cfg_fn!(rustc_attrs))),
@@ -800,6 +810,29 @@
     }}
 }
 
+impl<'a> PostExpansionVisitor<'a> {
+    fn check_abi(&self, abi: Abi, span: Span) {
+        match abi {
+            Abi::RustIntrinsic =>
+                gate_feature_post!(&self, intrinsics, span,
+                                   "intrinsics are subject to change"),
+            Abi::PlatformIntrinsic => {
+                gate_feature_post!(&self, platform_intrinsics, span,
+                                   "platform intrinsics are experimental and possibly buggy")
+            },
+            Abi::Vectorcall => {
+                gate_feature_post!(&self, abi_vectorcall, span,
+                                   "vectorcall is experimental and subject to change")
+            }
+            Abi::RustCall => {
+                gate_feature_post!(&self, unboxed_closures, span,
+                                   "rust-call ABI is subject to change");
+            }
+            _ => {}
+        }
+    }
+}
+
 impl<'a> Visitor for PostExpansionVisitor<'a> {
     fn visit_attribute(&mut self, attr: &ast::Attribute) {
         if !self.context.cm.span_allows_unstable(attr.span) {
@@ -831,21 +864,7 @@
                                        across platforms, it is recommended to \
                                        use `#[link(name = \"foo\")]` instead")
                 }
-                match foreign_module.abi {
-                    Abi::RustIntrinsic =>
-                        gate_feature_post!(&self, intrinsics, i.span,
-                                           "intrinsics are subject to change"),
-                    Abi::PlatformIntrinsic => {
-                        gate_feature_post!(&self, platform_intrinsics, i.span,
-                                           "platform intrinsics are experimental \
-                                            and possibly buggy")
-                    },
-                    Abi::Vectorcall => {
-                        gate_feature_post!(&self, abi_vectorcall, i.span,
-                                           "vectorcall is experimental and subject to change")
-                    }
-                    _ => ()
-                }
+                self.check_abi(foreign_module.abi, i.span);
             }
 
             ast::ItemKind::Fn(..) => {
@@ -928,6 +947,16 @@
         visit::walk_foreign_item(self, i)
     }
 
+    fn visit_ty(&mut self, ty: &ast::Ty) {
+        match ty.node {
+            ast::TyKind::BareFn(ref bare_fn_ty) => {
+                self.check_abi(bare_fn_ty.abi, ty.span);
+            }
+            _ => {}
+        }
+        visit::walk_ty(self, ty)
+    }
+
     fn visit_expr(&mut self, e: &ast::Expr) {
         match e.node {
             ast::ExprKind::Box(_) => {
@@ -1015,23 +1044,10 @@
         }
 
         match fn_kind {
-            FnKind::ItemFn(_, _, _, _, abi, _) if abi == Abi::RustIntrinsic => {
-                gate_feature_post!(&self, intrinsics,
-                                  span,
-                                  "intrinsics are subject to change")
-            }
             FnKind::ItemFn(_, _, _, _, abi, _) |
-            FnKind::Method(_, &ast::MethodSig { abi, .. }, _) => match abi {
-                Abi::RustCall => {
-                    gate_feature_post!(&self, unboxed_closures, span,
-                        "rust-call ABI is subject to change");
-                },
-                Abi::Vectorcall => {
-                    gate_feature_post!(&self, abi_vectorcall, span,
-                        "vectorcall is experimental and subject to change");
-                },
-                _ => {}
-            },
+            FnKind::Method(_, &ast::MethodSig { abi, .. }, _) => {
+                self.check_abi(abi, span);
+            }
             _ => {}
         }
         visit::walk_fn(self, fn_kind, fn_decl, block, span);
@@ -1044,7 +1060,10 @@
                                   ti.span,
                                   "associated constants are experimental")
             }
-            ast::TraitItemKind::Method(ref sig, _) => {
+            ast::TraitItemKind::Method(ref sig, ref block) => {
+                if block.is_none() {
+                    self.check_abi(sig.abi, ti.span);
+                }
                 if sig.constness == ast::Constness::Const {
                     gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable");
                 }
@@ -1108,14 +1127,13 @@
             }
             Some(list) => {
                 for mi in list {
-                    let name = match mi.node {
-                        ast::MetaItemKind::Word(ref word) => (*word).clone(),
-                        _ => {
-                            span_err!(span_handler, mi.span, E0556,
-                                      "malformed feature, expected just one word");
-                            continue
-                        }
-                    };
+                    let name = if mi.is_word() {
+                                   mi.name()
+                               } else {
+                                   span_err!(span_handler, mi.span, E0556,
+                                             "malformed feature, expected just one word");
+                                   continue
+                               };
                     if let Some(&(_, _, _, setter)) = ACTIVE_FEATURES.iter()
                         .find(|& &(n, _, _, _)| name == n) {
                         *(setter(&mut features)) = true;
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index 2147e8e..7b28952 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -237,7 +237,7 @@
                               cfg: ast::CrateConfig,
                               ts: tokenstream::TokenStream)
                               -> Parser<'a> {
-    tts_to_parser(sess, ts.tts, cfg)
+    tts_to_parser(sess, ts.to_tts(), cfg)
 }
 
 
diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs
index 0ad09fd..89ead21 100644
--- a/src/libsyntax/tokenstream.rs
+++ b/src/libsyntax/tokenstream.rs
@@ -16,27 +16,27 @@
 //! or a SequenceRepetition specifier (for the purpose of sequence generation during macro
 //! expansion).
 //!
-//! A TokenStream also has a slice view, `TokenSlice`, that is analogous to `str` for
-//! `String`: it allows the programmer to divvy up, explore, and otherwise partition a
-//! TokenStream as borrowed subsequences.
+//! ## Ownership
+//! TokenStreams are persistant data structures construced as ropes with reference
+//! counted-children. In general, this means that calling an operation on a TokenStream
+//! (such as `slice`) produces an entirely new TokenStream from the borrowed reference to
+//! the original. This essentially coerces TokenStreams into 'views' of their subparts,
+//! and a borrowed TokenStream is sufficient to build an owned TokenStream without taking
+//! ownership of the original.
 
 use ast::{self, AttrStyle, LitKind};
 use syntax_pos::{Span, DUMMY_SP, NO_EXPANSION};
-use codemap::Spanned;
+use codemap::{Spanned, combine_spans};
 use ext::base;
 use ext::tt::macro_parser;
 use parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration};
 use parse::lexer;
 use parse;
-use parse::token::{self, Token, Lit, InternedString, Nonterminal};
-use parse::token::Lit as TokLit;
+use parse::token::{self, Token, Lit, Nonterminal};
 
 use std::fmt;
-use std::mem;
-use std::ops::Index;
-use std::ops;
 use std::iter::*;
-
+use std::ops::{self, Index};
 use std::rc::Rc;
 
 /// A delimited sequence of token trees
@@ -135,6 +135,7 @@
             }
             TokenTree::Token(_, token::SpecialVarNt(..)) => 2,
             TokenTree::Token(_, token::MatchNt(..)) => 3,
+            TokenTree::Token(_, token::Interpolated(Nonterminal::NtTT(..))) => 1,
             TokenTree::Delimited(_, ref delimed) => delimed.tts.len() + 2,
             TokenTree::Sequence(_, ref seq) => seq.tts.len(),
             TokenTree::Token(..) => 0,
@@ -197,6 +198,9 @@
                          TokenTree::Token(sp, token::Ident(kind))];
                 v[index].clone()
             }
+            (&TokenTree::Token(_, token::Interpolated(Nonterminal::NtTT(ref tt))), _) => {
+                tt.clone().unwrap()
+            }
             (&TokenTree::Sequence(_, ref seq), _) => seq.tts[index].clone(),
             _ => panic!("Cannot expand a token tree"),
         }
@@ -331,27 +335,51 @@
 /// struct itself shouldn't be directly manipulated; the internal structure is not stable,
 /// and may be changed at any time in the future. The operators will not, however (except
 /// for signatures, later on).
-#[derive(Eq,Clone,Hash,RustcEncodable,RustcDecodable)]
+#[derive(Clone, Eq, Hash, RustcEncodable, RustcDecodable)]
 pub struct TokenStream {
-    pub span: Span,
-    pub tts: Vec<TokenTree>,
+    ts: InternalTS,
+}
+
+// NB If Leaf access proves to be slow, inroducing a secondary Leaf without the bounds
+// for unsliced Leafs may lead to some performance improvemenet.
+#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+pub enum InternalTS {
+    Empty(Span),
+    Leaf {
+        tts: Rc<Vec<TokenTree>>,
+        offset: usize,
+        len: usize,
+        sp: Span,
+    },
+    Node {
+        left: Rc<InternalTS>,
+        right: Rc<InternalTS>,
+        len: usize,
+        sp: Span,
+    },
 }
 
 impl fmt::Debug for TokenStream {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        if self.tts.len() == 0 {
-            write!(f, "([empty")?;
-        } else {
-            write!(f, "([")?;
-            write!(f, "{:?}", self.tts[0])?;
+        self.ts.fmt(f)
+    }
+}
 
-            for tt in self.tts.iter().skip(1) {
-                write!(f, ",{:?}", tt)?;
+impl fmt::Debug for InternalTS {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            InternalTS::Empty(..) => Ok(()),
+            InternalTS::Leaf { ref tts, offset, len, .. } => {
+                for t in tts.iter().skip(offset).take(len) {
+                    try!(write!(f, "{:?}", t));
+                }
+                Ok(())
+            }
+            InternalTS::Node { ref left, ref right, .. } => {
+                try!(left.fmt(f));
+                right.fmt(f)
             }
         }
-        write!(f, "|")?;
-        self.span.fmt(f)?;
-        write!(f, "])")
     }
 }
 
@@ -359,7 +387,7 @@
 /// equality, see `eq_unspanned`.
 impl PartialEq<TokenStream> for TokenStream {
     fn eq(&self, other: &TokenStream) -> bool {
-        self.tts == other.tts
+        self.iter().eq(other.iter())
     }
 }
 
@@ -404,6 +432,59 @@
     }
 }
 
+impl InternalTS {
+    fn len(&self) -> usize {
+        match *self {
+            InternalTS::Empty(..) => 0,
+            InternalTS::Leaf { len, .. } => len,
+            InternalTS::Node { len, .. } => len,
+        }
+    }
+
+    fn span(&self) -> Span {
+        match *self {
+            InternalTS::Empty(sp) |
+            InternalTS::Leaf { sp, .. } |
+            InternalTS::Node { sp, .. } => sp,
+        }
+    }
+
+    fn slice(&self, range: ops::Range<usize>) -> TokenStream {
+        let from = range.start;
+        let to = range.end;
+        if from == to {
+            return TokenStream::mk_empty();
+        }
+        if from > to {
+            panic!("Invalid range: {} to {}", from, to);
+        }
+        if from == 0 && to == self.len() {
+            return TokenStream { ts: self.clone() }; /* should be cheap */
+        }
+        match *self {
+            InternalTS::Empty(..) => panic!("Invalid index"),
+            InternalTS::Leaf { ref tts, offset, .. } => {
+                let offset = offset + from;
+                let len = to - from;
+                TokenStream::mk_sub_leaf(tts.clone(),
+                                         offset,
+                                         len,
+                                         covering_span(&tts[offset..offset + len]))
+            }
+            InternalTS::Node { ref left, ref right, .. } => {
+                let left_len = left.len();
+                if to <= left_len {
+                    left.slice(range)
+                } else if from >= left_len {
+                    right.slice(from - left_len..to - left_len)
+                } else {
+                    TokenStream::concat(left.slice(from..left_len), right.slice(0..to - left_len))
+                }
+            }
+        }
+    }
+}
+
 /// TokenStream operators include basic destructuring, boolean operations, `maybe_...`
 /// operations, and `maybe_..._prefix` operations. Boolean operations are straightforward,
 /// indicating information about the structure of the stream. The `maybe_...` operations
@@ -415,129 +496,149 @@
 ///
 ///    `maybe_path_prefix("a::b::c(a,b,c).foo()") -> (a::b::c, "(a,b,c).foo()")`
 impl TokenStream {
-    /// Convert a vector of `TokenTree`s into a `TokenStream`.
-    pub fn from_tts(trees: Vec<TokenTree>) -> TokenStream {
-        let span = covering_span(&trees);
+    pub fn mk_empty() -> TokenStream {
+        TokenStream { ts: InternalTS::Empty(DUMMY_SP) }
+    }
+
+    fn mk_spanned_empty(sp: Span) -> TokenStream {
+        TokenStream { ts: InternalTS::Empty(sp) }
+    }
+
+    fn mk_leaf(tts: Rc<Vec<TokenTree>>, sp: Span) -> TokenStream {
+        let len = tts.len();
         TokenStream {
-            tts: trees,
-            span: span,
+            ts: InternalTS::Leaf {
+                tts: tts,
+                offset: 0,
+                len: len,
+                sp: sp,
+            },
         }
     }
 
-    /// Copies all of the TokenTrees from the TokenSlice, appending them to the stream.
-    pub fn append_stream(mut self, ts2: &TokenSlice) {
-        for tt in ts2.iter() {
-            self.tts.push(tt.clone());
+    fn mk_sub_leaf(tts: Rc<Vec<TokenTree>>, offset: usize, len: usize, sp: Span) -> TokenStream {
+        TokenStream {
+            ts: InternalTS::Leaf {
+                tts: tts,
+                offset: offset,
+                len: len,
+                sp: sp,
+            },
         }
-        self.span = covering_span(&self.tts[..]);
+    }
+
+    fn mk_int_node(left: Rc<InternalTS>,
+                   right: Rc<InternalTS>,
+                   len: usize,
+                   sp: Span)
+                   -> TokenStream {
+        TokenStream {
+            ts: InternalTS::Node {
+                left: left,
+                right: right,
+                len: len,
+                sp: sp,
+            },
+        }
+    }
+
+    /// Convert a vector of `TokenTree`s into a `TokenStream`.
+    pub fn from_tts(trees: Vec<TokenTree>) -> TokenStream {
+        let span = covering_span(&trees[..]);
+        TokenStream::mk_leaf(Rc::new(trees), span)
     }
 
     /// Manually change a TokenStream's span.
     pub fn respan(self, span: Span) -> TokenStream {
-        TokenStream {
-            tts: self.tts,
-            span: span,
-        }
-    }
-
-    /// Construct a TokenStream from an ast literal.
-    pub fn from_ast_lit_str(lit: ast::Lit) -> Option<TokenStream> {
-        match lit.node {
-            LitKind::Str(val, _) => {
-                let val = TokLit::Str_(token::intern(&val));
-                Some(TokenStream::from_tts(vec![TokenTree::Token(lit.span,
-                                                                 Token::Literal(val, None))]))
+        match self.ts {
+            InternalTS::Empty(..) => TokenStream::mk_spanned_empty(span),
+            InternalTS::Leaf { tts, offset, len, .. } => {
+                TokenStream::mk_sub_leaf(tts, offset, len, span)
             }
-            _ => None,
+            InternalTS::Node { left, right, len, .. } => {
+                TokenStream::mk_int_node(left, right, len, span)
+            }
         }
-
     }
 
-    /// Convert a vector of TokenTrees into a parentheses-delimited TokenStream.
-    pub fn as_paren_delimited_stream(tts: Vec<TokenTree>) -> TokenStream {
-        let new_sp = covering_span(&tts);
-
-        let new_delim = Rc::new(Delimited {
-            delim: token::DelimToken::Paren,
-            open_span: DUMMY_SP,
-            tts: tts,
-            close_span: DUMMY_SP,
-        });
-
-        TokenStream::from_tts(vec![TokenTree::Delimited(new_sp, new_delim)])
+    /// Concatenates two TokenStreams into a new TokenStream
+    pub fn concat(left: TokenStream, right: TokenStream) -> TokenStream {
+        let new_len = left.len() + right.len();
+        let new_span = combine_spans(left.span(), right.span());
+        TokenStream::mk_int_node(Rc::new(left.ts), Rc::new(right.ts), new_len, new_span)
     }
 
-    /// Convert an interned string into a one-element TokenStream.
-    pub fn from_interned_string_as_ident(s: InternedString) -> TokenStream {
-        TokenStream::from_tts(vec![TokenTree::Token(DUMMY_SP,
-                                                    Token::Ident(token::str_to_ident(&s[..])))])
-    }
-}
-
-/// TokenSlices are 'views' of `TokenStream's; they fit the same role as `str`s do for
-/// `String`s. In general, most TokenStream manipulations will be refocusing their internal
-/// contents by taking a TokenSlice and then using indexing and the provided operators.
-#[derive(PartialEq, Eq, Debug)]
-pub struct TokenSlice([TokenTree]);
-
-impl ops::Deref for TokenStream {
-    type Target = TokenSlice;
-
-    fn deref(&self) -> &TokenSlice {
-        let tts: &[TokenTree] = &*self.tts;
-        unsafe { mem::transmute(tts) }
-    }
-}
-
-impl TokenSlice {
-    /// Convert a borrowed TokenTree slice into a borrowed TokenSlice.
-    fn from_tts(tts: &[TokenTree]) -> &TokenSlice {
-        unsafe { mem::transmute(tts) }
-    }
-
-    /// Indicates whether the `TokenStream` is empty.
+    /// Indicate if the TokenStream is empty.
     pub fn is_empty(&self) -> bool {
         self.len() == 0
     }
 
-    /// Return the `TokenSlice`'s length.
+    /// Return a TokenStream's length.
     pub fn len(&self) -> usize {
-        self.0.len()
+        self.ts.len()
     }
 
-    /// Check equality versus another TokenStream, ignoring span information.
-    pub fn eq_unspanned(&self, other: &TokenSlice) -> bool {
-        if self.len() != other.len() {
-            return false;
-        }
-        for (tt1, tt2) in self.iter().zip(other.iter()) {
-            if !tt1.eq_unspanned(tt2) {
-                return false;
+    /// Convert a TokenStream into a vector of borrowed TokenTrees.
+    pub fn to_vec(&self) -> Vec<&TokenTree> {
+        fn internal_to_vec(ts: &InternalTS) -> Vec<&TokenTree> {
+            match *ts {
+                InternalTS::Empty(..) => Vec::new(),
+                InternalTS::Leaf { ref tts, offset, len, .. } => {
+                    tts[offset..offset + len].iter().collect()
+                }
+                InternalTS::Node { ref left, ref right, .. } => {
+                    let mut v1 = internal_to_vec(left);
+                    let mut v2 = internal_to_vec(right);
+                    v1.append(&mut v2);
+                    v1
+                }
             }
         }
-        true
+        internal_to_vec(&self.ts)
     }
 
-    /// Compute a span that covers the entire TokenSlice (eg, one wide enough to include
-    /// the entire slice). If the inputs share expansion identification, it is preserved.
-    /// If they do not, it is discarded.
-    pub fn covering_span(&self) -> Span {
-        covering_span(&self.0)
+    /// Convert a TokenStream into a vector of TokenTrees (by cloning the TokenTrees).
+    /// (This operation is an O(n) deep copy of the underlying structure.)
+    pub fn to_tts(&self) -> Vec<TokenTree> {
+        self.to_vec().into_iter().cloned().collect::<Vec<TokenTree>>()
     }
 
-    /// Indicates where the stream is of the form `= <ts>`, where `<ts>` is a continued
-    /// `TokenStream`.
-    pub fn is_assignment(&self) -> bool {
-        self.maybe_assignment().is_some()
+    /// Return the TokenStream's span.
+    pub fn span(&self) -> Span {
+        self.ts.span()
     }
 
-    /// Returns the RHS of an assigment.
-    pub fn maybe_assignment(&self) -> Option<&TokenSlice> {
-        if !(self.len() > 1) {
-            return None;
+    /// Returns an iterator over a TokenStream (as a sequence of TokenTrees).
+    pub fn iter<'a>(&self) -> Iter {
+        Iter { vs: self, idx: 0 }
+    }
+
+    /// Splits a TokenStream based on the provided `&TokenTree -> bool` predicate.
+    pub fn split<P>(&self, pred: P) -> Split<P>
+        where P: FnMut(&TokenTree) -> bool
+    {
+        Split {
+            vs: self,
+            pred: pred,
+            finished: false,
+            idx: 0,
         }
+    }
 
-        Some(&self[1..])
+    /// Produce a slice of the input TokenStream from the `from` index, inclusive, to the
+    /// `to` index, non-inclusive.
+    pub fn slice(&self, range: ops::Range<usize>) -> TokenStream {
+        self.ts.slice(range)
+    }
+
+    /// Slice starting at the provided index, inclusive.
+    pub fn slice_from(&self, from: ops::RangeFrom<usize>) -> TokenStream {
+        self.slice(from.start..self.len())
+    }
+
+    /// Slice up to the provided index, non-inclusive.
+    pub fn slice_to(&self, to: ops::RangeTo<usize>) -> TokenStream {
+        self.slice(0..to.end)
     }
 
     /// Indicates where the stream is a single, delimited expression (e.g., `(a,b,c)` or
@@ -547,50 +648,15 @@
     }
 
     /// Returns the inside of the delimited term as a new TokenStream.
-    pub fn maybe_delimited(&self) -> Option<&TokenSlice> {
+    pub fn maybe_delimited(&self) -> Option<TokenStream> {
         if !(self.len() == 1) {
             return None;
         }
 
+        // FIXME It would be nice to change Delimited to move the Rc around the TokenTree
+        // vector directly in order to avoid the clone here.
         match self[0] {
-            TokenTree::Delimited(_, ref rc) => Some(TokenSlice::from_tts(&*rc.tts)),
-            _ => None,
-        }
-    }
-
-    /// Returns a list of `TokenSlice`s if the stream is a delimited list, breaking the
-    /// stream on commas.
-    pub fn maybe_comma_list(&self) -> Option<Vec<&TokenSlice>> {
-        let maybe_tts = self.maybe_delimited();
-
-        let ts: &TokenSlice;
-        match maybe_tts {
-            Some(t) => {
-                ts = t;
-            }
-            None => {
-                return None;
-            }
-        }
-
-        let splits: Vec<&TokenSlice> = ts.split(|x| match *x {
-                TokenTree::Token(_, Token::Comma) => true,
-                _ => false,
-            })
-            .filter(|x| x.len() > 0)
-            .collect();
-
-        Some(splits)
-    }
-
-    /// Returns a Nonterminal if it is Interpolated.
-    pub fn maybe_interpolated_nonterminal(&self) -> Option<Nonterminal> {
-        if !(self.len() == 1) {
-            return None;
-        }
-
-        match self[0] {
-            TokenTree::Token(_, Token::Interpolated(ref nt)) => Some(nt.clone()),
+            TokenTree::Delimited(_, ref rc) => Some(TokenStream::from_tts(rc.tts.clone())),
             _ => None,
         }
     }
@@ -606,180 +672,54 @@
             return None;
         }
 
-        let tok = if let Some(tts) = self.maybe_delimited() {
-            if tts.len() != 1 {
-                return None;
-            }
-            &tts[0]
-        } else {
-            &self[0]
-        };
-
-        match *tok {
+        match self[0] {
             TokenTree::Token(_, Token::Ident(t)) => Some(t),
             _ => None,
         }
     }
 
-    /// Indicates if the stream is exactly one literal
-    pub fn is_lit(&self) -> bool {
-        self.maybe_lit().is_some()
-    }
-
-    /// Returns a literal
-    pub fn maybe_lit(&self) -> Option<token::Lit> {
-        if !(self.len() == 1) {
-            return None;
-        }
-
-        let tok = if let Some(tts) = self.maybe_delimited() {
-            if tts.len() != 1 {
-                return None;
-            }
-            &tts[0]
-        } else {
-            &self[0]
-        };
-
-        match *tok {
-            TokenTree::Token(_, Token::Literal(l, _)) => Some(l),
-            _ => None,
-        }
-    }
-
-    /// Returns an AST string literal if the TokenStream is either a normal ('cooked') or
-    /// raw string literal.
-    pub fn maybe_str(&self) -> Option<ast::Lit> {
-        if !(self.len() == 1) {
-            return None;
-        }
-
-        match self[0] {
-            TokenTree::Token(sp, Token::Literal(Lit::Str_(s), _)) => {
-                let l = LitKind::Str(token::intern_and_get_ident(&parse::str_lit(&s.as_str())),
-                                     ast::StrStyle::Cooked);
-                Some(Spanned {
-                    node: l,
-                    span: sp,
-                })
-            }
-            TokenTree::Token(sp, Token::Literal(Lit::StrRaw(s, n), _)) => {
-                let l = LitKind::Str(token::intern_and_get_ident(&parse::raw_str_lit(&s.as_str())),
-                                     ast::StrStyle::Raw(n));
-                Some(Spanned {
-                    node: l,
-                    span: sp,
-                })
-            }
-            _ => None,
-        }
-    }
-
-    /// This operation extracts the path prefix , returning an AST path struct and the remainder
-    /// of the stream (if it finds one). To be more specific, a tokenstream that has a valid,
-    /// non-global path as a prefix (eg `foo(bar, baz)`, `foo::bar(bar)`, but *not*
-    /// `::foo::bar(baz)`) will yield the path and the remaining tokens (as a slice). The previous
-    /// examples will yield
-    /// `Some((Path { segments = vec![foo], ... }, [(bar, baz)]))`,
-    /// `Some((Path { segments = vec![foo, bar] }, [(baz)]))`,
-    /// and `None`, respectively.
-    pub fn maybe_path_prefix(&self) -> Option<(ast::Path, &TokenSlice)> {
-        let mut segments: Vec<ast::PathSegment> = Vec::new();
-
-        let path: Vec<&TokenTree> = self.iter()
-            .take_while(|x| x.is_ident() || x.eq_token(Token::ModSep))
-            .collect::<Vec<&TokenTree>>();
-
-        let path_size = path.len();
-        if path_size == 0 {
-            return None;
-        }
-
-        let cov_span = self[..path_size].covering_span();
-        let rst = &self[path_size..];
-
-        let fst_id = path[0];
-
-        if let Some(id) = fst_id.maybe_ident() {
-            segments.push(ast::PathSegment {
-                identifier: id,
-                parameters: ast::PathParameters::none(),
-            });
-        } else {
-            return None;
-        }
-
-        // Let's use a state machine to parse out the rest.
-        enum State {
-            Mod, // Expect a `::`, or return None otherwise.
-            Ident, // Expect an ident, or return None otherwise.
-        }
-        let mut state = State::Mod;
-
-        for p in &path[1..] {
-            match state {
-                State::Mod => {
-                    // State 0: ['::' -> state 1, else return None]
-                    if p.eq_token(Token::ModSep) {
-                        state = State::Ident;
-                    } else {
-                        return None;
-                    }
-                }
-                State::Ident => {
-                    // State 1: [ident -> state 0, else return None]
-                    if let Some(id) = p.maybe_ident() {
-                        segments.push(ast::PathSegment {
-                            identifier: id,
-                            parameters: ast::PathParameters::none(),
-                        });
-                        state = State::Mod;
-                    } else {
-                        return None;
-                    }
-                }
+    /// Compares two TokenStreams, checking equality without regarding span information.
+    pub fn eq_unspanned(&self, other: &TokenStream) -> bool {
+        for (t1, t2) in self.iter().zip(other.iter()) {
+            if !t1.eq_unspanned(t2) {
+                return false;
             }
         }
-
-        let path = ast::Path {
-            span: cov_span,
-            global: false,
-            segments: segments,
-        };
-        Some((path, rst))
+        true
     }
 
-    /// Returns an iterator over a TokenSlice (as a sequence of TokenStreams).
-    fn iter(&self) -> Iter {
-        Iter { vs: self }
-    }
+    /// Convert a vector of TokenTrees into a parentheses-delimited TokenStream.
+    pub fn as_delimited_stream(tts: Vec<TokenTree>, delim: token::DelimToken) -> TokenStream {
+        let new_sp = covering_span(&tts);
 
-    /// Splits a TokenSlice based on the provided `&TokenTree -> bool` predicate.
-    fn split<P>(&self, pred: P) -> Split<P>
-        where P: FnMut(&TokenTree) -> bool
-    {
-        Split {
-            vs: self,
-            pred: pred,
-            finished: false,
-        }
+        let new_delim = Rc::new(Delimited {
+            delim: delim,
+            open_span: DUMMY_SP,
+            tts: tts,
+            close_span: DUMMY_SP,
+        });
+
+        TokenStream::from_tts(vec![TokenTree::Delimited(new_sp, new_delim)])
     }
 }
 
+// FIXME Reimplement this iterator to hold onto a slice iterator for a leaf, getting the
+// next leaf's iterator when the current one is exhausted.
 pub struct Iter<'a> {
-    vs: &'a TokenSlice,
+    vs: &'a TokenStream,
+    idx: usize,
 }
 
 impl<'a> Iterator for Iter<'a> {
     type Item = &'a TokenTree;
 
     fn next(&mut self) -> Option<&'a TokenTree> {
-        if self.vs.is_empty() {
+        if self.vs.is_empty() || self.idx >= self.vs.len() {
             return None;
         }
 
-        let ret = Some(&self.vs[0]);
-        self.vs = &self.vs[1..];
+        let ret = Some(&self.vs[self.idx]);
+        self.idx = self.idx + 1;
         ret
     }
 }
@@ -787,29 +727,35 @@
 pub struct Split<'a, P>
     where P: FnMut(&TokenTree) -> bool
 {
-    vs: &'a TokenSlice,
+    vs: &'a TokenStream,
     pred: P,
     finished: bool,
+    idx: usize,
 }
 
 impl<'a, P> Iterator for Split<'a, P>
     where P: FnMut(&TokenTree) -> bool
 {
-    type Item = &'a TokenSlice;
+    type Item = TokenStream;
 
-    fn next(&mut self) -> Option<&'a TokenSlice> {
+    fn next(&mut self) -> Option<TokenStream> {
         if self.finished {
             return None;
         }
+        if self.idx >= self.vs.len() {
+            self.finished = true;
+            return None;
+        }
 
-        match self.vs.iter().position(|x| (self.pred)(x)) {
+        let mut lookup = self.vs.iter().skip(self.idx);
+        match lookup.position(|x| (self.pred)(&x)) {
             None => {
                 self.finished = true;
-                Some(&self.vs[..])
+                Some(self.vs.slice_from(self.idx..))
             }
-            Some(idx) => {
-                let ret = Some(&self.vs[..idx]);
-                self.vs = &self.vs[idx + 1..];
+            Some(edx) => {
+                let ret = Some(self.vs.slice(self.idx..self.idx + edx));
+                self.idx += edx + 1;
                 ret
             }
         }
@@ -820,79 +766,29 @@
     type Output = TokenTree;
 
     fn index(&self, index: usize) -> &TokenTree {
-        Index::index(&**self, index)
+        &self.ts[index]
     }
 }
 
-impl ops::Index<ops::Range<usize>> for TokenStream {
-    type Output = TokenSlice;
-
-    fn index(&self, index: ops::Range<usize>) -> &TokenSlice {
-        Index::index(&**self, index)
-    }
-}
-
-impl ops::Index<ops::RangeTo<usize>> for TokenStream {
-    type Output = TokenSlice;
-
-    fn index(&self, index: ops::RangeTo<usize>) -> &TokenSlice {
-        Index::index(&**self, index)
-    }
-}
-
-impl ops::Index<ops::RangeFrom<usize>> for TokenStream {
-    type Output = TokenSlice;
-
-    fn index(&self, index: ops::RangeFrom<usize>) -> &TokenSlice {
-        Index::index(&**self, index)
-    }
-}
-
-impl ops::Index<ops::RangeFull> for TokenStream {
-    type Output = TokenSlice;
-
-    fn index(&self, _index: ops::RangeFull) -> &TokenSlice {
-        Index::index(&**self, _index)
-    }
-}
-
-impl Index<usize> for TokenSlice {
+impl Index<usize> for InternalTS {
     type Output = TokenTree;
 
     fn index(&self, index: usize) -> &TokenTree {
-        &self.0[index]
-    }
-}
-
-impl ops::Index<ops::Range<usize>> for TokenSlice {
-    type Output = TokenSlice;
-
-    fn index(&self, index: ops::Range<usize>) -> &TokenSlice {
-        TokenSlice::from_tts(&self.0[index])
-    }
-}
-
-impl ops::Index<ops::RangeTo<usize>> for TokenSlice {
-    type Output = TokenSlice;
-
-    fn index(&self, index: ops::RangeTo<usize>) -> &TokenSlice {
-        TokenSlice::from_tts(&self.0[index])
-    }
-}
-
-impl ops::Index<ops::RangeFrom<usize>> for TokenSlice {
-    type Output = TokenSlice;
-
-    fn index(&self, index: ops::RangeFrom<usize>) -> &TokenSlice {
-        TokenSlice::from_tts(&self.0[index])
-    }
-}
-
-impl ops::Index<ops::RangeFull> for TokenSlice {
-    type Output = TokenSlice;
-
-    fn index(&self, _index: ops::RangeFull) -> &TokenSlice {
-        TokenSlice::from_tts(&self.0[_index])
+        if self.len() <= index {
+            panic!("Index {} too large for {:?}", index, self);
+        }
+        match *self {
+            InternalTS::Empty(..) => panic!("Invalid index"),
+            InternalTS::Leaf { ref tts, offset, .. } => tts.get(index + offset).unwrap(),
+            InternalTS::Node { ref left, ref right, .. } => {
+                let left_len = left.len();
+                if index < left_len {
+                    Index::index(&**left, index)
+                } else {
+                    Index::index(&**right, index - left_len)
+                }
+            }
+        }
     }
 }
 
@@ -900,9 +796,8 @@
 #[cfg(test)]
 mod tests {
     use super::*;
-    use ast;
     use syntax_pos::{Span, BytePos, NO_EXPANSION, DUMMY_SP};
-    use parse::token::{self, str_to_ident, Token, Lit};
+    use parse::token::{self, str_to_ident, Token};
     use util::parser_testing::string_to_tts;
     use std::rc::Rc;
 
@@ -914,6 +809,93 @@
         }
     }
 
+    fn as_paren_delimited_stream(tts: Vec<TokenTree>) -> TokenStream {
+        TokenStream::as_delimited_stream(tts, token::DelimToken::Paren)
+    }
+
+    #[test]
+    fn test_concat() {
+        let test_res = TokenStream::from_tts(string_to_tts("foo::bar::baz".to_string()));
+        let test_fst = TokenStream::from_tts(string_to_tts("foo::bar".to_string()));
+        let test_snd = TokenStream::from_tts(string_to_tts("::baz".to_string()));
+        let eq_res = TokenStream::concat(test_fst, test_snd);
+        assert_eq!(test_res.len(), 5);
+        assert_eq!(eq_res.len(), 5);
+        assert_eq!(test_res.eq_unspanned(&eq_res), true);
+    }
+
+    #[test]
+    fn test_from_to_bijection() {
+        let test_start = string_to_tts("foo::bar(baz)".to_string());
+        let test_end = TokenStream::from_tts(string_to_tts("foo::bar(baz)".to_string())).to_tts();
+        assert_eq!(test_start, test_end)
+    }
+
+    #[test]
+    fn test_to_from_bijection() {
+        let test_start = TokenStream::from_tts(string_to_tts("foo::bar(baz)".to_string()));
+        let test_end = TokenStream::from_tts(test_start.clone().to_tts());
+        assert_eq!(test_start, test_end)
+    }
+
+    #[test]
+    fn test_eq_0() {
+        let test_res = TokenStream::from_tts(string_to_tts("foo".to_string()));
+        let test_eqs = TokenStream::from_tts(string_to_tts("foo".to_string()));
+        assert_eq!(test_res, test_eqs)
+    }
+
+    #[test]
+    fn test_eq_1() {
+        let test_res = TokenStream::from_tts(string_to_tts("::bar::baz".to_string()));
+        let test_eqs = TokenStream::from_tts(string_to_tts("::bar::baz".to_string()));
+        assert_eq!(test_res, test_eqs)
+    }
+
+    #[test]
+    fn test_eq_2() {
+        let test_res = TokenStream::from_tts(string_to_tts("foo::bar".to_string()));
+        let test_eqs = TokenStream::from_tts(string_to_tts("foo::bar::baz".to_string()));
+        assert_eq!(test_res, test_eqs.slice(0..3))
+    }
+
+    #[test]
+    fn test_eq_3() {
+        let test_res = TokenStream::from_tts(string_to_tts("".to_string()));
+        let test_eqs = TokenStream::from_tts(string_to_tts("".to_string()));
+        assert_eq!(test_res, test_eqs)
+    }
+
+    #[test]
+    fn test_diseq_0() {
+        let test_res = TokenStream::from_tts(string_to_tts("::bar::baz".to_string()));
+        let test_eqs = TokenStream::from_tts(string_to_tts("bar::baz".to_string()));
+        assert_eq!(test_res == test_eqs, false)
+    }
+
+    #[test]
+    fn test_diseq_1() {
+        let test_res = TokenStream::from_tts(string_to_tts("(bar,baz)".to_string()));
+        let test_eqs = TokenStream::from_tts(string_to_tts("bar,baz".to_string()));
+        assert_eq!(test_res == test_eqs, false)
+    }
+
+    #[test]
+    fn test_slice_0() {
+        let test_res = TokenStream::from_tts(string_to_tts("foo::bar".to_string()));
+        let test_eqs = TokenStream::from_tts(string_to_tts("foo::bar::baz".to_string()));
+        assert_eq!(test_res, test_eqs.slice(0..3))
+    }
+
+    #[test]
+    fn test_slice_1() {
+        let test_res = TokenStream::from_tts(string_to_tts("foo::bar::baz".to_string()))
+            .slice(2..3);
+        let test_eqs = TokenStream::from_tts(vec![TokenTree::Token(sp(5,8),
+                                                    token::Ident(str_to_ident("bar")))]);
+        assert_eq!(test_res, test_eqs)
+    }
+
     #[test]
     fn test_is_empty() {
         let test0 = TokenStream::from_tts(Vec::new());
@@ -944,38 +926,6 @@
     }
 
     #[test]
-    fn test_is_assign() {
-        let test0 = TokenStream::from_tts(string_to_tts("= bar::baz".to_string()));
-        let test1 = TokenStream::from_tts(string_to_tts("= \"5\"".to_string()));
-        let test2 = TokenStream::from_tts(string_to_tts("= 5".to_string()));
-        let test3 = TokenStream::from_tts(string_to_tts("(foo = 10)".to_string()));
-        let test4 = TokenStream::from_tts(string_to_tts("= (foo,bar,baz)".to_string()));
-        let test5 = TokenStream::from_tts(string_to_tts("".to_string()));
-
-        assert_eq!(test0.is_assignment(), true);
-        assert_eq!(test1.is_assignment(), true);
-        assert_eq!(test2.is_assignment(), true);
-        assert_eq!(test3.is_assignment(), false);
-        assert_eq!(test4.is_assignment(), true);
-        assert_eq!(test5.is_assignment(), false);
-    }
-
-    #[test]
-    fn test_is_lit() {
-        let test0 = TokenStream::from_tts(string_to_tts("\"foo\"".to_string()));
-        let test1 = TokenStream::from_tts(string_to_tts("5".to_string()));
-        let test2 = TokenStream::from_tts(string_to_tts("foo".to_string()));
-        let test3 = TokenStream::from_tts(string_to_tts("foo::bar".to_string()));
-        let test4 = TokenStream::from_tts(string_to_tts("foo(bar)".to_string()));
-
-        assert_eq!(test0.is_lit(), true);
-        assert_eq!(test1.is_lit(), true);
-        assert_eq!(test2.is_lit(), false);
-        assert_eq!(test3.is_lit(), false);
-        assert_eq!(test4.is_lit(), false);
-    }
-
-    #[test]
     fn test_is_ident() {
         let test0 = TokenStream::from_tts(string_to_tts("\"foo\"".to_string()));
         let test1 = TokenStream::from_tts(string_to_tts("5".to_string()));
@@ -991,62 +941,6 @@
     }
 
     #[test]
-    fn test_maybe_assignment() {
-        let test0_input = TokenStream::from_tts(string_to_tts("= bar::baz".to_string()));
-        let test1_input = TokenStream::from_tts(string_to_tts("= \"5\"".to_string()));
-        let test2_input = TokenStream::from_tts(string_to_tts("= 5".to_string()));
-        let test3_input = TokenStream::from_tts(string_to_tts("(foo = 10)".to_string()));
-        let test4_input = TokenStream::from_tts(string_to_tts("= (foo,bar,baz)".to_string()));
-        let test5_input = TokenStream::from_tts(string_to_tts("".to_string()));
-
-        let test0 = test0_input.maybe_assignment();
-        let test1 = test1_input.maybe_assignment();
-        let test2 = test2_input.maybe_assignment();
-        let test3 = test3_input.maybe_assignment();
-        let test4 = test4_input.maybe_assignment();
-        let test5 = test5_input.maybe_assignment();
-
-        let test0_expected = TokenStream::from_tts(vec![TokenTree::Token(sp(2, 5),
-                                                        token::Ident(str_to_ident("bar"))),
-                                       TokenTree::Token(sp(5, 7), token::ModSep),
-                                       TokenTree::Token(sp(7, 10),
-                                                        token::Ident(str_to_ident("baz")))]);
-        assert_eq!(test0, Some(&test0_expected[..]));
-
-        let test1_expected = TokenStream::from_tts(vec![TokenTree::Token(sp(2, 5),
-                                            token::Literal(Lit::Str_(token::intern("5")), None))]);
-        assert_eq!(test1, Some(&test1_expected[..]));
-
-        let test2_expected = TokenStream::from_tts(vec![TokenTree::Token( sp(2,3)
-                                       , token::Literal(
-                                           Lit::Integer(
-                                             token::intern(&(5.to_string()))),
-                                             None))]);
-        assert_eq!(test2, Some(&test2_expected[..]));
-
-        assert_eq!(test3, None);
-
-
-        let test4_tts = vec![TokenTree::Token(sp(3, 6), token::Ident(str_to_ident("foo"))),
-                             TokenTree::Token(sp(6, 7), token::Comma),
-                             TokenTree::Token(sp(7, 10), token::Ident(str_to_ident("bar"))),
-                             TokenTree::Token(sp(10, 11), token::Comma),
-                             TokenTree::Token(sp(11, 14), token::Ident(str_to_ident("baz")))];
-
-        let test4_expected = TokenStream::from_tts(vec![TokenTree::Delimited(sp(2, 15),
-                                                Rc::new(Delimited {
-                                                    delim: token::DelimToken::Paren,
-                                                    open_span: sp(2, 3),
-                                                    tts: test4_tts,
-                                                    close_span: sp(14, 15),
-                                                }))]);
-        assert_eq!(test4, Some(&test4_expected[..]));
-
-        assert_eq!(test5, None);
-
-    }
-
-    #[test]
     fn test_maybe_delimited() {
         let test0_input = TokenStream::from_tts(string_to_tts("foo(bar::baz)".to_string()));
         let test1_input = TokenStream::from_tts(string_to_tts("(bar::baz)".to_string()));
@@ -1070,7 +964,7 @@
                                        TokenTree::Token(sp(4, 6), token::ModSep),
                                        TokenTree::Token(sp(6, 9),
                                                         token::Ident(str_to_ident("baz")))]);
-        assert_eq!(test1, Some(&test1_expected[..]));
+        assert_eq!(test1, Some(test1_expected));
 
         let test2_expected = TokenStream::from_tts(vec![TokenTree::Token(sp(1, 4),
                                                         token::Ident(str_to_ident("foo"))),
@@ -1080,7 +974,7 @@
                                        TokenTree::Token(sp(8, 9), token::Comma),
                                        TokenTree::Token(sp(9, 12),
                                                         token::Ident(str_to_ident("baz")))]);
-        assert_eq!(test2, Some(&test2_expected[..]));
+        assert_eq!(test2, Some(test2_expected));
 
         assert_eq!(test3, None);
 
@@ -1089,72 +983,6 @@
         assert_eq!(test5, None);
     }
 
-    #[test]
-    fn test_maybe_comma_list() {
-        let test0_input = TokenStream::from_tts(string_to_tts("foo(bar::baz)".to_string()));
-        let test1_input = TokenStream::from_tts(string_to_tts("(bar::baz)".to_string()));
-        let test2_input = TokenStream::from_tts(string_to_tts("(foo,bar,baz)".to_string()));
-        let test3_input = TokenStream::from_tts(string_to_tts("(foo::bar,bar,baz)".to_string()));
-        let test4_input = TokenStream::from_tts(string_to_tts("(foo,bar,baz)(zab,rab)"
-            .to_string()));
-        let test5_input = TokenStream::from_tts(string_to_tts("(foo,bar,baz)foo".to_string()));
-        let test6_input = TokenStream::from_tts(string_to_tts("".to_string()));
-        // The following is supported behavior!
-        let test7_input = TokenStream::from_tts(string_to_tts("(foo,bar,)".to_string()));
-
-        let test0 = test0_input.maybe_comma_list();
-        let test1 = test1_input.maybe_comma_list();
-        let test2 = test2_input.maybe_comma_list();
-        let test3 = test3_input.maybe_comma_list();
-        let test4 = test4_input.maybe_comma_list();
-        let test5 = test5_input.maybe_comma_list();
-        let test6 = test6_input.maybe_comma_list();
-        let test7 = test7_input.maybe_comma_list();
-
-        assert_eq!(test0, None);
-
-        let test1_stream = TokenStream::from_tts(vec![TokenTree::Token(sp(1, 4),
-                                                        token::Ident(str_to_ident("bar"))),
-                                       TokenTree::Token(sp(4, 6), token::ModSep),
-                                       TokenTree::Token(sp(6, 9),
-                                                        token::Ident(str_to_ident("baz")))]);
-
-        let test1_expected: Vec<&TokenSlice> = vec![&test1_stream[..]];
-        assert_eq!(test1, Some(test1_expected));
-
-        let test2_foo = TokenStream::from_tts(vec![TokenTree::Token(sp(1, 4),
-                                                        token::Ident(str_to_ident("foo")))]);
-        let test2_bar = TokenStream::from_tts(vec![TokenTree::Token(sp(5, 8),
-                                                        token::Ident(str_to_ident("bar")))]);
-        let test2_baz = TokenStream::from_tts(vec![TokenTree::Token(sp(9, 12),
-                                                        token::Ident(str_to_ident("baz")))]);
-        let test2_expected: Vec<&TokenSlice> = vec![&test2_foo[..], &test2_bar[..], &test2_baz[..]];
-        assert_eq!(test2, Some(test2_expected));
-
-        let test3_path = TokenStream::from_tts(vec![TokenTree::Token(sp(1, 4),
-                                                        token::Ident(str_to_ident("foo"))),
-                                       TokenTree::Token(sp(4, 6), token::ModSep),
-                                       TokenTree::Token(sp(6, 9),
-                                                        token::Ident(str_to_ident("bar")))]);
-        let test3_bar = TokenStream::from_tts(vec![TokenTree::Token(sp(10, 13),
-                                                        token::Ident(str_to_ident("bar")))]);
-        let test3_baz = TokenStream::from_tts(vec![TokenTree::Token(sp(14, 17),
-                                                        token::Ident(str_to_ident("baz")))]);
-        let test3_expected: Vec<&TokenSlice> =
-            vec![&test3_path[..], &test3_bar[..], &test3_baz[..]];
-        assert_eq!(test3, Some(test3_expected));
-
-        assert_eq!(test4, None);
-
-        assert_eq!(test5, None);
-
-        assert_eq!(test6, None);
-
-
-        let test7_expected: Vec<&TokenSlice> = vec![&test2_foo[..], &test2_bar[..]];
-        assert_eq!(test7, Some(test7_expected));
-    }
-
     // pub fn maybe_ident(&self) -> Option<ast::Ident>
     #[test]
     fn test_maybe_ident() {
@@ -1171,86 +999,10 @@
         assert_eq!(test4, None);
     }
 
-    // pub fn maybe_lit(&self) -> Option<token::Lit>
     #[test]
-    fn test_maybe_lit() {
-        let test0 = TokenStream::from_tts(string_to_tts("\"foo\"".to_string())).maybe_lit();
-        let test1 = TokenStream::from_tts(string_to_tts("5".to_string())).maybe_lit();
-        let test2 = TokenStream::from_tts(string_to_tts("foo".to_string())).maybe_lit();
-        let test3 = TokenStream::from_tts(string_to_tts("foo::bar".to_string())).maybe_lit();
-        let test4 = TokenStream::from_tts(string_to_tts("foo(bar)".to_string())).maybe_lit();
-
-        assert_eq!(test0, Some(Lit::Str_(token::intern("foo"))));
-        assert_eq!(test1, Some(Lit::Integer(token::intern(&(5.to_string())))));
-        assert_eq!(test2, None);
-        assert_eq!(test3, None);
-        assert_eq!(test4, None);
-    }
-
-    #[test]
-    fn test_maybe_path_prefix() {
-        let test0_input = TokenStream::from_tts(string_to_tts("foo(bar::baz)".to_string()));
-        let test1_input = TokenStream::from_tts(string_to_tts("(bar::baz)".to_string()));
-        let test2_input = TokenStream::from_tts(string_to_tts("(foo,bar,baz)".to_string()));
-        let test3_input = TokenStream::from_tts(string_to_tts("foo::bar(bar,baz)".to_string()));
-
-        let test0 = test0_input.maybe_path_prefix();
-        let test1 = test1_input.maybe_path_prefix();
-        let test2 = test2_input.maybe_path_prefix();
-        let test3 = test3_input.maybe_path_prefix();
-
-        let test0_tts = vec![TokenTree::Token(sp(4, 7), token::Ident(str_to_ident("bar"))),
-                             TokenTree::Token(sp(7, 9), token::ModSep),
-                             TokenTree::Token(sp(9, 12), token::Ident(str_to_ident("baz")))];
-
-        let test0_stream = TokenStream::from_tts(vec![TokenTree::Delimited(sp(3, 13),
-                                                               Rc::new(Delimited {
-                                                                   delim: token::DelimToken::Paren,
-                                                                   open_span: sp(3, 4),
-                                                                   tts: test0_tts,
-                                                                   close_span: sp(12, 13),
-                                                               }))]);
-
-        let test0_expected = Some((ast::Path::from_ident(sp(0, 3), str_to_ident("foo")),
-                                   &test0_stream[..]));
-        assert_eq!(test0, test0_expected);
-
-        assert_eq!(test1, None);
-        assert_eq!(test2, None);
-
-        let test3_path = ast::Path {
-            span: sp(0, 8),
-            global: false,
-            segments: vec![ast::PathSegment {
-                               identifier: str_to_ident("foo"),
-                               parameters: ast::PathParameters::none(),
-                           },
-                           ast::PathSegment {
-                               identifier: str_to_ident("bar"),
-                               parameters: ast::PathParameters::none(),
-                           }],
-        };
-
-        let test3_tts = vec![TokenTree::Token(sp(9, 12), token::Ident(str_to_ident("bar"))),
-                             TokenTree::Token(sp(12, 13), token::Comma),
-                             TokenTree::Token(sp(13, 16), token::Ident(str_to_ident("baz")))];
-
-        let test3_stream = TokenStream::from_tts(vec![TokenTree::Delimited(sp(8, 17),
-                                                               Rc::new(Delimited {
-                                                                   delim: token::DelimToken::Paren,
-                                                                   open_span: sp(8, 9),
-                                                                   tts: test3_tts,
-                                                                   close_span: sp(16, 17),
-                                                               }))]);
-        let test3_expected = Some((test3_path, &test3_stream[..]));
-        assert_eq!(test3, test3_expected);
-    }
-
-    #[test]
-    fn test_as_paren_delimited_stream() {
-        let test0 = TokenStream::as_paren_delimited_stream(string_to_tts("foo,bar,".to_string()));
-        let test1 = TokenStream::as_paren_delimited_stream(string_to_tts("baz(foo,bar)"
-            .to_string()));
+    fn test_as_delimited_stream() {
+        let test0 = as_paren_delimited_stream(string_to_tts("foo,bar,".to_string()));
+        let test1 = as_paren_delimited_stream(string_to_tts("baz(foo,bar)".to_string()));
 
         let test0_tts = vec![TokenTree::Token(sp(0, 3), token::Ident(str_to_ident("foo"))),
                              TokenTree::Token(sp(3, 4), token::Comma),
@@ -1290,5 +1042,4 @@
 
         assert_eq!(test1, test1_stream);
     }
-
 }
diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs
index 80e2a92..e09a64e 100644
--- a/src/libsyntax_ext/deriving/mod.rs
+++ b/src/libsyntax_ext/deriving/mod.rs
@@ -10,7 +10,7 @@
 
 //! The compiler code necessary to implement the `#[derive]` extensions.
 
-use syntax::ast::{self, MetaItem, MetaItemKind};
+use syntax::ast::{MetaItem, self};
 use syntax::attr::AttrMetaMethods;
 use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxEnv};
 use syntax::ext::base::{MultiDecorator, MultiItemDecorator, MultiModifier};
@@ -98,15 +98,14 @@
             let mut eq_span = None;
 
             for titem in traits.iter().rev() {
-                let tname = match titem.node {
-                    MetaItemKind::Word(ref tname) => tname,
-                    _ => {
-                        cx.span_err(titem.span, "malformed `derive` entry");
-                        continue;
-                    }
-                };
+                let tname = if titem.is_word() {
+                                titem.name() }
+                            else {
+                                cx.span_err(titem.span, "malformed `derive` entry");
+                                continue;
+                            };
 
-                if !(is_builtin_trait(tname) || cx.ecfg.enable_custom_derive()) {
+                if !(is_builtin_trait(&tname) || cx.ecfg.enable_custom_derive()) {
                     feature_gate::emit_feature_err(&cx.parse_sess.span_diagnostic,
                                                    "custom_derive",
                                                    titem.span,
diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs
index 94bb78e..1f6f57c 100644
--- a/src/libsyntax_ext/format.rs
+++ b/src/libsyntax_ext/format.rs
@@ -406,7 +406,9 @@
                             let arg_idx = match arg_index_consumed.get_mut(i) {
                                 None => 0, // error already emitted elsewhere
                                 Some(offset) => {
-                                    let arg_idx = self.arg_index_map[i][*offset];
+                                    let ref idx_map = self.arg_index_map[i];
+                                    // unwrap_or branch: error already emitted elsewhere
+                                    let arg_idx = *idx_map.get(*offset).unwrap_or(&0);
                                     *offset += 1;
                                     arg_idx
                                 }
diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs
index c96be8f..0f17180 100644
--- a/src/libsyntax_pos/lib.rs
+++ b/src/libsyntax_pos/lib.rs
@@ -193,6 +193,20 @@
         }
     }
 
+    pub fn from_span(primary_span: Span) -> MultiSpan {
+        MultiSpan {
+            primary_spans: vec![primary_span],
+            span_labels: vec![]
+        }
+    }
+
+    pub fn from_spans(vec: Vec<Span>) -> MultiSpan {
+        MultiSpan {
+            primary_spans: vec,
+            span_labels: vec![]
+        }
+    }
+
     pub fn push_span_label(&mut self, span: Span, label: String) {
         self.span_labels.push((span, label));
     }
@@ -240,10 +254,7 @@
 
 impl From<Span> for MultiSpan {
     fn from(span: Span) -> MultiSpan {
-        MultiSpan {
-            primary_spans: vec![span],
-            span_labels: vec![]
-        }
+        MultiSpan::from_span(span)
     }
 }
 
@@ -254,6 +265,10 @@
 // For code appearing from the command line
 pub const COMMAND_LINE_EXPN: ExpnId = ExpnId(!1);
 
+// For code generated by a procedural macro, without knowing which
+// Used in `qquote!`
+pub const PROC_EXPN: ExpnId = ExpnId(!2);
+
 impl ExpnId {
     pub fn from_u32(id: u32) -> ExpnId {
         ExpnId(id)
diff --git a/src/libunwind/build.rs b/src/libunwind/build.rs
index ebe6fd5..fd446f5 100644
--- a/src/libunwind/build.rs
+++ b/src/libunwind/build.rs
@@ -16,7 +16,7 @@
     let target = env::var("TARGET").unwrap();
 
     if target.contains("linux") {
-        if target.contains("musl") && (target.contains("x86_64") || target.contains("i686")) {
+        if target.contains("musl") && !target.contains("mips") {
             println!("cargo:rustc-link-lib=static=unwind");
         } else if !target.contains("android") {
             println!("cargo:rustc-link-lib=gcc_s");
diff --git a/src/libunwind/libunwind.rs b/src/libunwind/libunwind.rs
index d9b6c9e..5e242db 100644
--- a/src/libunwind/libunwind.rs
+++ b/src/libunwind/libunwind.rs
@@ -10,38 +10,15 @@
 
 #![allow(bad_style)]
 
-use libc;
-
-#[cfg(any(not(target_arch = "arm"), target_os = "ios"))]
-pub use self::_Unwind_Action::*;
-#[cfg(target_arch = "arm")]
-pub use self::_Unwind_State::*;
-pub use self::_Unwind_Reason_Code::*;
-
-#[cfg(any(not(target_arch = "arm"), target_os = "ios"))]
-#[repr(C)]
-#[derive(Clone, Copy)]
-pub enum _Unwind_Action {
-    _UA_SEARCH_PHASE = 1,
-    _UA_CLEANUP_PHASE = 2,
-    _UA_HANDLER_FRAME = 4,
-    _UA_FORCE_UNWIND = 8,
-    _UA_END_OF_STACK = 16,
+macro_rules! cfg_if {
+    ( $( if #[cfg( $meta:meta )] { $($it1:item)* } else { $($it2:item)* } )* ) =>
+        ( $( $( #[cfg($meta)] $it1)* $( #[cfg(not($meta))] $it2)* )* )
 }
 
-#[cfg(target_arch = "arm")]
-#[repr(C)]
-#[derive(Clone, Copy)]
-pub enum _Unwind_State {
-    _US_VIRTUAL_UNWIND_FRAME = 0,
-    _US_UNWIND_FRAME_STARTING = 1,
-    _US_UNWIND_FRAME_RESUME = 2,
-    _US_ACTION_MASK = 3,
-    _US_FORCE_UNWIND = 8,
-    _US_END_OF_STACK = 16,
-}
+use libc::{c_int, c_void, uintptr_t};
 
 #[repr(C)]
+#[derive(Copy, Clone, PartialEq)]
 pub enum _Unwind_Reason_Code {
     _URC_NO_REASON = 0,
     _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
@@ -52,17 +29,15 @@
     _URC_HANDLER_FOUND = 6,
     _URC_INSTALL_CONTEXT = 7,
     _URC_CONTINUE_UNWIND = 8,
-    _URC_FAILURE = 9, // used only by ARM EABI
+    _URC_FAILURE = 9, // used only by ARM EHABI
 }
+pub use self::_Unwind_Reason_Code::*;
 
 pub type _Unwind_Exception_Class = u64;
-
-pub type _Unwind_Word = libc::uintptr_t;
-pub type _Unwind_Ptr = libc::uintptr_t;
-
-pub type _Unwind_Trace_Fn = extern "C" fn(ctx: *mut _Unwind_Context, arg: *mut libc::c_void)
+pub type _Unwind_Word = uintptr_t;
+pub type _Unwind_Ptr = uintptr_t;
+pub type _Unwind_Trace_Fn = extern "C" fn(ctx: *mut _Unwind_Context, arg: *mut c_void)
                                           -> _Unwind_Reason_Code;
-
 #[cfg(target_arch = "x86")]
 pub const unwinder_private_data_size: usize = 5;
 
@@ -99,6 +74,164 @@
 
 pub type _Unwind_Exception_Cleanup_Fn = extern "C" fn(unwind_code: _Unwind_Reason_Code,
                                                       exception: *mut _Unwind_Exception);
+extern "C" {
+    #[unwind]
+    pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !;
+    pub fn _Unwind_DeleteException(exception: *mut _Unwind_Exception);
+    pub fn _Unwind_GetLanguageSpecificData(ctx: *mut _Unwind_Context) -> *mut c_void;
+    pub fn _Unwind_GetRegionStart(ctx: *mut _Unwind_Context) -> _Unwind_Ptr;
+    pub fn _Unwind_GetTextRelBase(ctx: *mut _Unwind_Context) -> _Unwind_Ptr;
+    pub fn _Unwind_GetDataRelBase(ctx: *mut _Unwind_Context) -> _Unwind_Ptr;
+}
+
+cfg_if! {
+if #[cfg(not(any(all(target_os = "android", target_arch = "arm"),
+                 all(target_os = "linux", target_arch = "arm"))))] {
+    // Not ARM EHABI
+    #[repr(C)]
+    #[derive(Copy, Clone, PartialEq)]
+    pub enum _Unwind_Action {
+        _UA_SEARCH_PHASE = 1,
+        _UA_CLEANUP_PHASE = 2,
+        _UA_HANDLER_FRAME = 4,
+        _UA_FORCE_UNWIND = 8,
+        _UA_END_OF_STACK = 16,
+    }
+    pub use self::_Unwind_Action::*;
+
+    extern "C" {
+        pub fn _Unwind_GetGR(ctx: *mut _Unwind_Context, reg_index: c_int) -> _Unwind_Word;
+        pub fn _Unwind_SetGR(ctx: *mut _Unwind_Context, reg_index: c_int, value: _Unwind_Word);
+        pub fn _Unwind_GetIP(ctx: *mut _Unwind_Context) -> _Unwind_Word;
+        pub fn _Unwind_SetIP(ctx: *mut _Unwind_Context, value: _Unwind_Word);
+        pub fn _Unwind_GetIPInfo(ctx: *mut _Unwind_Context, ip_before_insn: *mut c_int)
+                                 -> _Unwind_Word;
+        pub fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void;
+    }
+
+} else {
+    // ARM EHABI
+    #[repr(C)]
+    #[derive(Copy, Clone, PartialEq)]
+    pub enum _Unwind_State {
+        _US_VIRTUAL_UNWIND_FRAME = 0,
+        _US_UNWIND_FRAME_STARTING = 1,
+        _US_UNWIND_FRAME_RESUME = 2,
+        _US_ACTION_MASK = 3,
+        _US_FORCE_UNWIND = 8,
+        _US_END_OF_STACK = 16,
+    }
+    pub use self::_Unwind_State::*;
+
+    #[repr(C)]
+    enum _Unwind_VRS_Result {
+        _UVRSR_OK = 0,
+        _UVRSR_NOT_IMPLEMENTED = 1,
+        _UVRSR_FAILED = 2,
+    }
+    #[repr(C)]
+    enum _Unwind_VRS_RegClass {
+        _UVRSC_CORE = 0,
+        _UVRSC_VFP = 1,
+        _UVRSC_FPA = 2,
+        _UVRSC_WMMXD = 3,
+        _UVRSC_WMMXC = 4,
+    }
+    use self::_Unwind_VRS_RegClass::*;
+    #[repr(C)]
+    enum _Unwind_VRS_DataRepresentation {
+        _UVRSD_UINT32 = 0,
+        _UVRSD_VFPX = 1,
+        _UVRSD_FPAX = 2,
+        _UVRSD_UINT64 = 3,
+        _UVRSD_FLOAT = 4,
+        _UVRSD_DOUBLE = 5,
+    }
+    use self::_Unwind_VRS_DataRepresentation::*;
+
+    pub const UNWIND_POINTER_REG: c_int = 12;
+    pub const UNWIND_IP_REG: c_int = 15;
+
+    extern "C" {
+        fn _Unwind_VRS_Get(ctx: *mut _Unwind_Context,
+                           regclass: _Unwind_VRS_RegClass,
+                           regno: _Unwind_Word,
+                           repr: _Unwind_VRS_DataRepresentation,
+                           data: *mut c_void)
+                           -> _Unwind_VRS_Result;
+
+        fn _Unwind_VRS_Set(ctx: *mut _Unwind_Context,
+                           regclass: _Unwind_VRS_RegClass,
+                           regno: _Unwind_Word,
+                           repr: _Unwind_VRS_DataRepresentation,
+                           data: *mut c_void)
+                           -> _Unwind_VRS_Result;
+    }
+
+    // On Android or ARM/Linux, these are implemented as macros:
+
+    pub unsafe fn _Unwind_GetGR(ctx: *mut _Unwind_Context, reg_index: c_int) -> _Unwind_Word {
+        let mut val: _Unwind_Word = 0;
+        _Unwind_VRS_Get(ctx, _UVRSC_CORE, reg_index as _Unwind_Word, _UVRSD_UINT32,
+                        &mut val as *mut _ as *mut c_void);
+        val
+    }
+
+    pub unsafe fn _Unwind_SetGR(ctx: *mut _Unwind_Context, reg_index: c_int, value: _Unwind_Word) {
+        let mut value = value;
+        _Unwind_VRS_Set(ctx, _UVRSC_CORE, reg_index as _Unwind_Word, _UVRSD_UINT32,
+                        &mut value as *mut _ as *mut c_void);
+    }
+
+    pub unsafe fn _Unwind_GetIP(ctx: *mut _Unwind_Context)
+                                -> _Unwind_Word {
+        let val = _Unwind_GetGR(ctx, UNWIND_IP_REG);
+        (val & !1) as _Unwind_Word
+    }
+
+    pub unsafe fn _Unwind_SetIP(ctx: *mut _Unwind_Context,
+                                value: _Unwind_Word) {
+        // Propagate thumb bit to instruction pointer
+        let thumb_state = _Unwind_GetGR(ctx, UNWIND_IP_REG) & 1;
+        let value = value | thumb_state;
+        _Unwind_SetGR(ctx, UNWIND_IP_REG, value);
+    }
+
+    pub unsafe fn _Unwind_GetIPInfo(ctx: *mut _Unwind_Context,
+                                    ip_before_insn: *mut c_int)
+                                    -> _Unwind_Word {
+        *ip_before_insn = 0;
+        _Unwind_GetIP(ctx)
+    }
+
+    // This function also doesn't exist on Android or ARM/Linux, so make it a no-op
+    pub unsafe fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void {
+        pc
+    }
+}
+
+if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] {
+    // Not 32-bit iOS
+    extern "C" {
+        #[unwind]
+        pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
+        pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
+                                 trace_argument: *mut c_void)
+                                 -> _Unwind_Reason_Code;
+    }
+} else {
+    // 32-bit iOS uses SjLj and does not provide _Unwind_Backtrace()
+    extern "C" {
+        #[unwind]
+        pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
+    }
+
+    #[inline]
+    pub unsafe fn _Unwind_RaiseException(exc: *mut _Unwind_Exception) -> _Unwind_Reason_Code {
+        _Unwind_SjLj_RaiseException(exc)
+    }
+}
+} // cfg_if!
 
 #[cfg_attr(any(all(target_os = "linux", not(target_env = "musl")),
                target_os = "freebsd",
@@ -127,122 +260,3 @@
            link(name = "gcc_eh"))]
 #[cfg(not(cargobuild))]
 extern "C" {}
-
-extern "C" {
-    // iOS on armv7 uses SjLj exceptions and requires to link
-    // against corresponding routine (..._SjLj_...)
-    #[cfg(not(all(target_os = "ios", target_arch = "arm")))]
-    #[unwind]
-    pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
-
-    #[cfg(all(target_os = "ios", target_arch = "arm"))]
-    #[unwind]
-    fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
-
-    pub fn _Unwind_DeleteException(exception: *mut _Unwind_Exception);
-
-    #[unwind]
-    pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !;
-
-    // No native _Unwind_Backtrace on iOS
-    #[cfg(not(all(target_os = "ios", target_arch = "arm")))]
-    pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
-                             trace_argument: *mut libc::c_void)
-                             -> _Unwind_Reason_Code;
-
-    // available since GCC 4.2.0, should be fine for our purpose
-    #[cfg(all(not(all(target_os = "android", target_arch = "arm")),
-              not(all(target_os = "linux", target_arch = "arm"))))]
-    pub fn _Unwind_GetIPInfo(ctx: *mut _Unwind_Context,
-                             ip_before_insn: *mut libc::c_int)
-                             -> libc::uintptr_t;
-
-    pub fn _Unwind_GetLanguageSpecificData(ctx: *mut _Unwind_Context) -> _Unwind_Ptr;
-    pub fn _Unwind_GetRegionStart(ctx: *mut _Unwind_Context) -> _Unwind_Ptr;
-    pub fn _Unwind_GetTextRelBase(ctx: *mut _Unwind_Context) -> _Unwind_Ptr;
-    pub fn _Unwind_GetDataRelBase(ctx: *mut _Unwind_Context) -> _Unwind_Ptr;
-    pub fn _Unwind_SetGR(ctx: *mut _Unwind_Context, reg_index: libc::c_int, value: _Unwind_Ptr);
-    pub fn _Unwind_SetIP(ctx: *mut _Unwind_Context, value: _Unwind_Ptr);
-
-    #[cfg(all(not(target_os = "android"),
-              not(all(target_os = "linux", target_arch = "arm"))))]
-    pub fn _Unwind_FindEnclosingFunction(pc: *mut libc::c_void) -> *mut libc::c_void;
-}
-
-// ... and now we just providing access to SjLj counterspart
-// through a standard name to hide those details from others
-// (see also comment above regarding _Unwind_RaiseException)
-#[cfg(all(target_os = "ios", target_arch = "arm"))]
-#[inline]
-pub unsafe fn _Unwind_RaiseException(exc: *mut _Unwind_Exception) -> _Unwind_Reason_Code {
-    _Unwind_SjLj_RaiseException(exc)
-}
-
-// On android, the function _Unwind_GetIP is a macro, and this is the
-// expansion of the macro. This is all copy/pasted directly from the
-// header file with the definition of _Unwind_GetIP.
-#[cfg(any(all(target_os = "android", target_arch = "arm"),
-          all(target_os = "linux", target_arch = "arm")))]
-pub unsafe fn _Unwind_GetIP(ctx: *mut _Unwind_Context) -> libc::uintptr_t {
-    #[repr(C)]
-    enum _Unwind_VRS_Result {
-        _UVRSR_OK = 0,
-        _UVRSR_NOT_IMPLEMENTED = 1,
-        _UVRSR_FAILED = 2,
-    }
-    #[repr(C)]
-    enum _Unwind_VRS_RegClass {
-        _UVRSC_CORE = 0,
-        _UVRSC_VFP = 1,
-        _UVRSC_FPA = 2,
-        _UVRSC_WMMXD = 3,
-        _UVRSC_WMMXC = 4,
-    }
-    #[repr(C)]
-    enum _Unwind_VRS_DataRepresentation {
-        _UVRSD_UINT32 = 0,
-        _UVRSD_VFPX = 1,
-        _UVRSD_FPAX = 2,
-        _UVRSD_UINT64 = 3,
-        _UVRSD_FLOAT = 4,
-        _UVRSD_DOUBLE = 5,
-    }
-
-    type _Unwind_Word = libc::c_uint;
-    extern "C" {
-        fn _Unwind_VRS_Get(ctx: *mut _Unwind_Context,
-                           klass: _Unwind_VRS_RegClass,
-                           word: _Unwind_Word,
-                           repr: _Unwind_VRS_DataRepresentation,
-                           data: *mut libc::c_void)
-                           -> _Unwind_VRS_Result;
-    }
-
-    let mut val: _Unwind_Word = 0;
-    let ptr = &mut val as *mut _Unwind_Word;
-    let _ = _Unwind_VRS_Get(ctx,
-                            _Unwind_VRS_RegClass::_UVRSC_CORE,
-                            15,
-                            _Unwind_VRS_DataRepresentation::_UVRSD_UINT32,
-                            ptr as *mut libc::c_void);
-    (val & !1) as libc::uintptr_t
-}
-
-// This function doesn't exist on Android or ARM/Linux, so make it same
-// to _Unwind_GetIP
-#[cfg(any(all(target_os = "android", target_arch = "arm"),
-          all(target_os = "linux", target_arch = "arm")))]
-pub unsafe fn _Unwind_GetIPInfo(ctx: *mut _Unwind_Context,
-                                ip_before_insn: *mut libc::c_int)
-                                -> libc::uintptr_t {
-    *ip_before_insn = 0;
-    _Unwind_GetIP(ctx)
-}
-
-// This function also doesn't exist on Android or ARM/Linux, so make it
-// a no-op
-#[cfg(any(target_os = "android",
-          all(target_os = "linux", target_arch = "arm")))]
-pub unsafe fn _Unwind_FindEnclosingFunction(pc: *mut libc::c_void) -> *mut libc::c_void {
-    pc
-}
diff --git a/src/llvm b/src/llvm
index 7ca76af..d1cc489 160000
--- a/src/llvm
+++ b/src/llvm
@@ -1 +1 @@
-Subproject commit 7ca76af03bb04659562890d6b4f223fffe0d748f
+Subproject commit d1cc48989b13780f21c408fef17dceb104a09c9d
diff --git a/src/rustc/Cargo.lock b/src/rustc/Cargo.lock
index 4def60e..0b2287c 100644
--- a/src/rustc/Cargo.lock
+++ b/src/rustc/Cargo.lock
@@ -105,6 +105,7 @@
  "rustc 0.0.0",
  "rustc_back 0.0.0",
  "rustc_const_math 0.0.0",
+ "rustc_errors 0.0.0",
  "serialize 0.0.0",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
diff --git a/src/rustc/std_shim/Cargo.lock b/src/rustc/std_shim/Cargo.lock
index bad4696..70aef55 100644
--- a/src/rustc/std_shim/Cargo.lock
+++ b/src/rustc/std_shim/Cargo.lock
@@ -18,7 +18,7 @@
 dependencies = [
  "build_helper 0.1.0",
  "core 0.0.0",
- "gcc 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.27 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.0.0",
 ]
 
@@ -49,7 +49,7 @@
 
 [[package]]
 name = "gcc"
-version = "0.3.26"
+version = "0.3.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -101,7 +101,7 @@
  "build_helper 0.1.0",
  "collections 0.0.0",
  "core 0.0.0",
- "gcc 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.27 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.0.0",
  "panic_abort 0.0.0",
  "panic_unwind 0.0.0",
diff --git a/src/rustc/std_shim/Cargo.toml b/src/rustc/std_shim/Cargo.toml
index 5602ef8..693cbe0 100644
--- a/src/rustc/std_shim/Cargo.toml
+++ b/src/rustc/std_shim/Cargo.toml
@@ -46,3 +46,4 @@
 [features]
 jemalloc = ["std/jemalloc"]
 debug-jemalloc = ["std/debug-jemalloc"]
+backtrace = ["std/backtrace"]
diff --git a/src/rustllvm/ArchiveWrapper.cpp b/src/rustllvm/ArchiveWrapper.cpp
index 1e7b04c..1e873b5 100644
--- a/src/rustllvm/ArchiveWrapper.cpp
+++ b/src/rustllvm/ArchiveWrapper.cpp
@@ -16,24 +16,62 @@
 using namespace llvm;
 using namespace llvm::object;
 
-struct LLVMRustArchiveMember {
+struct RustArchiveMember {
   const char *filename;
   const char *name;
   Archive::Child child;
 
-  LLVMRustArchiveMember(): filename(NULL), name(NULL),
+  RustArchiveMember(): filename(NULL), name(NULL),
 #if LLVM_VERSION_MINOR >= 8
     child(NULL, NULL, NULL)
 #else
     child(NULL, NULL)
 #endif
   {}
-  ~LLVMRustArchiveMember() {}
+  ~RustArchiveMember() {}
 };
 
-typedef OwningBinary<Archive> RustArchive;
 
-extern "C" void*
+struct RustArchiveIterator {
+    Archive::child_iterator cur;
+    Archive::child_iterator end;
+#if LLVM_VERSION_MINOR >= 9
+    Error err;
+#endif
+};
+
+enum class LLVMRustArchiveKind {
+    Other,
+    GNU,
+    MIPS64,
+    BSD,
+    COFF,
+};
+
+static Archive::Kind
+from_rust(LLVMRustArchiveKind kind)
+{
+    switch (kind) {
+    case LLVMRustArchiveKind::GNU:
+        return Archive::K_GNU;
+    case LLVMRustArchiveKind::MIPS64:
+        return Archive::K_MIPS64;
+    case LLVMRustArchiveKind::BSD:
+        return Archive::K_BSD;
+    case LLVMRustArchiveKind::COFF:
+        return Archive::K_COFF;
+    default:
+      llvm_unreachable("Bad ArchiveKind.");
+  }
+}
+
+typedef OwningBinary<Archive> *LLVMRustArchiveRef;
+typedef RustArchiveMember *LLVMRustArchiveMemberRef;
+typedef Archive::Child *LLVMRustArchiveChildRef;
+typedef Archive::Child const *LLVMRustArchiveChildConstRef;
+typedef RustArchiveIterator *LLVMRustArchiveIteratorRef;
+
+extern "C" LLVMRustArchiveRef
 LLVMRustOpenArchive(char *path) {
     ErrorOr<std::unique_ptr<MemoryBuffer>> buf_or = MemoryBuffer::getFile(path,
                                                                           -1,
@@ -43,11 +81,19 @@
         return nullptr;
     }
 
+#if LLVM_VERSION_MINOR <= 8
     ErrorOr<std::unique_ptr<Archive>> archive_or =
+#else
+    Expected<std::unique_ptr<Archive>> archive_or =
+#endif
         Archive::create(buf_or.get()->getMemBufferRef());
 
     if (!archive_or) {
+#if LLVM_VERSION_MINOR <= 8
         LLVMRustSetLastError(archive_or.getError().message().c_str());
+#else
+        LLVMRustSetLastError(toString(archive_or.takeError()).c_str());
+#endif
         return nullptr;
     }
 
@@ -58,29 +104,38 @@
 }
 
 extern "C" void
-LLVMRustDestroyArchive(RustArchive *ar) {
+LLVMRustDestroyArchive(LLVMRustArchiveRef ar) {
     delete ar;
 }
 
-struct RustArchiveIterator {
-    Archive::child_iterator cur;
-    Archive::child_iterator end;
-};
-
-extern "C" RustArchiveIterator*
-LLVMRustArchiveIteratorNew(RustArchive *ra) {
+extern "C" LLVMRustArchiveIteratorRef
+LLVMRustArchiveIteratorNew(LLVMRustArchiveRef ra) {
     Archive *ar = ra->getBinary();
     RustArchiveIterator *rai = new RustArchiveIterator();
+#if LLVM_VERSION_MINOR <= 8
     rai->cur = ar->child_begin();
+#else
+    rai->cur = ar->child_begin(rai->err);
+    if (rai->err) {
+        LLVMRustSetLastError(toString(std::move(rai->err)).c_str());
+        return NULL;
+    }
+#endif
     rai->end = ar->child_end();
     return rai;
 }
 
-extern "C" const Archive::Child*
-LLVMRustArchiveIteratorNext(RustArchiveIterator *rai) {
+extern "C" LLVMRustArchiveChildConstRef
+LLVMRustArchiveIteratorNext(LLVMRustArchiveIteratorRef rai) {
+#if LLVM_VERSION_MINOR >= 9
+    if (rai->err) {
+        LLVMRustSetLastError(toString(std::move(rai->err)).c_str());
+        return NULL;
+    }
+#endif
     if (rai->cur == rai->end)
         return NULL;
-#if LLVM_VERSION_MINOR >= 8
+#if LLVM_VERSION_MINOR == 8
     const ErrorOr<Archive::Child>* cur = rai->cur.operator->();
     if (!*cur) {
         LLVMRustSetLastError(cur->getError().message().c_str());
@@ -97,17 +152,17 @@
 }
 
 extern "C" void
-LLVMRustArchiveChildFree(Archive::Child *child) {
+LLVMRustArchiveChildFree(LLVMRustArchiveChildRef child) {
     delete child;
 }
 
 extern "C" void
-LLVMRustArchiveIteratorFree(RustArchiveIterator *rai) {
+LLVMRustArchiveIteratorFree(LLVMRustArchiveIteratorRef rai) {
     delete rai;
 }
 
 extern "C" const char*
-LLVMRustArchiveChildName(const Archive::Child *child, size_t *size) {
+LLVMRustArchiveChildName(LLVMRustArchiveChildConstRef child, size_t *size) {
     ErrorOr<StringRef> name_or_err = child->getName();
     if (name_or_err.getError())
         return NULL;
@@ -117,7 +172,7 @@
 }
 
 extern "C" const char*
-LLVMRustArchiveChildData(Archive::Child *child, size_t *size) {
+LLVMRustArchiveChildData(LLVMRustArchiveChildRef child, size_t *size) {
     StringRef buf;
     ErrorOr<StringRef> buf_or_err = child->getBuffer();
     if (buf_or_err.getError()) {
@@ -129,9 +184,10 @@
     return buf.data();
 }
 
-extern "C" LLVMRustArchiveMember*
-LLVMRustArchiveMemberNew(char *Filename, char *Name, Archive::Child *child) {
-    LLVMRustArchiveMember *Member = new LLVMRustArchiveMember;
+extern "C" LLVMRustArchiveMemberRef
+LLVMRustArchiveMemberNew(char *Filename, char *Name,
+			 LLVMRustArchiveChildRef child) {
+    RustArchiveMember *Member = new RustArchiveMember;
     Member->filename = Filename;
     Member->name = Name;
     if (child)
@@ -140,29 +196,51 @@
 }
 
 extern "C" void
-LLVMRustArchiveMemberFree(LLVMRustArchiveMember *Member) {
+LLVMRustArchiveMemberFree(LLVMRustArchiveMemberRef Member) {
     delete Member;
 }
 
-extern "C" int
+extern "C" LLVMRustResult
 LLVMRustWriteArchive(char *Dst,
                      size_t NumMembers,
-                     const LLVMRustArchiveMember **NewMembers,
+                     const LLVMRustArchiveMemberRef *NewMembers,
                      bool WriteSymbtab,
-                     Archive::Kind Kind) {
+                     LLVMRustArchiveKind rust_kind) {
+
+#if LLVM_VERSION_MINOR <= 8
   std::vector<NewArchiveIterator> Members;
+#else
+  std::vector<NewArchiveMember> Members;
+#endif
+  auto Kind = from_rust(rust_kind);
 
   for (size_t i = 0; i < NumMembers; i++) {
     auto Member = NewMembers[i];
     assert(Member->name);
     if (Member->filename) {
-#if LLVM_VERSION_MINOR >= 8
+#if LLVM_VERSION_MINOR >= 9
+      Expected<NewArchiveMember> MOrErr = NewArchiveMember::getFile(Member->filename, true);
+      if (!MOrErr) {
+        LLVMRustSetLastError(toString(MOrErr.takeError()).c_str());
+        return LLVMRustResult::Failure;
+      }
+      Members.push_back(std::move(*MOrErr));
+#elif LLVM_VERSION_MINOR == 8
       Members.push_back(NewArchiveIterator(Member->filename));
 #else
       Members.push_back(NewArchiveIterator(Member->filename, Member->name));
 #endif
     } else {
+#if LLVM_VERSION_MINOR <= 8
       Members.push_back(NewArchiveIterator(Member->child, Member->name));
+#else
+      Expected<NewArchiveMember> MOrErr = NewArchiveMember::getOldMember(Member->child, true);
+      if (!MOrErr) {
+        LLVMRustSetLastError(toString(MOrErr.takeError()).c_str());
+        return LLVMRustResult::Failure;
+      }
+      Members.push_back(std::move(*MOrErr));
+#endif
     }
   }
 #if LLVM_VERSION_MINOR >= 8
@@ -171,7 +249,7 @@
   auto pair = writeArchive(Dst, Members, WriteSymbtab, Kind, true);
 #endif
   if (!pair.second)
-    return 0;
+    return LLVMRustResult::Success;
   LLVMRustSetLastError(pair.second.message().c_str());
-  return -1;
+  return LLVMRustResult::Failure;
 }
diff --git a/src/rustllvm/ExecutionEngineWrapper.cpp b/src/rustllvm/ExecutionEngineWrapper.cpp
deleted file mode 100644
index b26ab44..0000000
--- a/src/rustllvm/ExecutionEngineWrapper.cpp
+++ /dev/null
@@ -1,111 +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.
-
-#include "rustllvm.h"
-
-#include "llvm/ExecutionEngine/SectionMemoryManager.h"
-
-using namespace llvm;
-using namespace llvm::sys;
-using namespace llvm::object;
-
-class RustJITMemoryManager : public SectionMemoryManager
-{
-    typedef SectionMemoryManager Base;
-
-    public:
-
-    RustJITMemoryManager() {}
-
-    uint64_t getSymbolAddress(const std::string &Name) override
-    {
-        return Base::getSymbolAddress(Name);
-    }
-};
-
-DEFINE_SIMPLE_CONVERSION_FUNCTIONS(RustJITMemoryManager, LLVMRustJITMemoryManagerRef)
-
-extern "C" LLVMBool LLVMRustLoadDynamicLibrary(const char *path)
-{
-    std::string err;
-    DynamicLibrary lib = DynamicLibrary::getPermanentLibrary(path, &err);
-
-    if (!lib.isValid())
-        LLVMRustSetLastError(err.c_str());
-
-    return lib.isValid();
-}
-
-// Calls LLVMAddModule;
-// exists for consistency with LLVMExecutionEngineRemoveModule
-extern "C" void LLVMExecutionEngineAddModule(
-    LLVMExecutionEngineRef eeref, LLVMModuleRef mref)
-{
-#ifdef _WIN32
-    // On Windows, MCJIT must generate ELF objects
-    std::string target = getProcessTriple();
-    target += "-elf";
-    target = Triple::normalize(target);
-    unwrap(mref)->setTargetTriple(target);
-#endif
-    LLVMAddModule(eeref, mref);
-}
-
-// LLVMRemoveModule exists in LLVM's C bindings,
-// but it requires pointless parameters
-extern "C" LLVMBool LLVMExecutionEngineRemoveModule(
-    LLVMExecutionEngineRef eeref, LLVMModuleRef mref)
-{
-    ExecutionEngine *ee = unwrap(eeref);
-    Module *m = unwrap(mref);
-
-    return ee->removeModule(m);
-}
-
-extern "C" LLVMExecutionEngineRef LLVMBuildExecutionEngine(LLVMModuleRef mod)
-{
-    // These are necessary for code generation to work properly.
-    InitializeNativeTarget();
-    InitializeNativeTargetAsmPrinter();
-    InitializeNativeTargetAsmParser();
-
-#ifdef _WIN32
-    // On Windows, MCJIT must generate ELF objects
-    std::string target = getProcessTriple();
-    target += "-elf";
-    target = Triple::normalize(target);
-    unwrap(mod)->setTargetTriple(target);
-#endif
-
-    std::string error_str;
-    TargetOptions options;
-
-    RustJITMemoryManager *mm = new RustJITMemoryManager;
-
-    ExecutionEngine *ee =
-        EngineBuilder(std::unique_ptr<Module>(unwrap(mod)))
-            .setMCJITMemoryManager(std::unique_ptr<RustJITMemoryManager>(mm))
-            .setEngineKind(EngineKind::JIT)
-            .setErrorStr(&error_str)
-            .setTargetOptions(options)
-            .create();
-
-    if (!ee)
-        LLVMRustSetLastError(error_str.c_str());
-
-    return wrap(ee);
-}
-
-extern "C" void LLVMExecutionEngineFinalizeObject(LLVMExecutionEngineRef eeref)
-{
-    ExecutionEngine *ee = unwrap(eeref);
-
-    ee->finalizeObject();
-}
diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp
index 3564f33..3a20bb2 100644
--- a/src/rustllvm/PassWrapper.cpp
+++ b/src/rustllvm/PassWrapper.cpp
@@ -17,6 +17,7 @@
 #include "llvm/Support/Host.h"
 #include "llvm/Analysis/TargetLibraryInfo.h"
 #include "llvm/Analysis/TargetTransformInfo.h"
+#include "llvm/IR/AutoUpgrade.h"
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/Target/TargetSubtargetInfo.h"
 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
@@ -54,41 +55,48 @@
   initializeTarget(Registry);
 }
 
-
-enum class SupportedPassKind {
+enum class LLVMRustPassKind {
+  Other,
   Function,
   Module,
-  Unsupported
 };
 
-extern "C" Pass*
+static LLVMRustPassKind
+to_rust(PassKind kind)
+{
+  switch (kind) {
+  case PT_Function:
+      return LLVMRustPassKind::Function;
+  case PT_Module:
+      return LLVMRustPassKind::Module;
+  default:
+      return LLVMRustPassKind::Other;
+  }
+}
+
+extern "C" LLVMPassRef
 LLVMRustFindAndCreatePass(const char *PassName) {
     StringRef SR(PassName);
     PassRegistry *PR = PassRegistry::getPassRegistry();
 
     const PassInfo *PI = PR->getPassInfo(SR);
     if (PI) {
-        return PI->createPass();
+      return wrap(PI->createPass());
     }
     return NULL;
 }
 
-extern "C" SupportedPassKind
-LLVMRustPassKind(Pass *pass) {
-    assert(pass);
-    PassKind passKind = pass->getPassKind();
-    if (passKind == PT_Module) {
-        return SupportedPassKind::Module;
-    } else if (passKind == PT_Function) {
-        return SupportedPassKind::Function;
-    } else {
-        return SupportedPassKind::Unsupported;
-    }
+extern "C" LLVMRustPassKind
+LLVMRustPassKind(LLVMPassRef rust_pass) {
+    assert(rust_pass);
+    Pass *pass = unwrap(rust_pass);
+    return to_rust(pass->getPassKind());
 }
 
 extern "C" void
-LLVMRustAddPass(LLVMPassManagerRef PM, Pass *pass) {
-    assert(pass);
+LLVMRustAddPass(LLVMPassManagerRef PM, LLVMPassRef rust_pass) {
+    assert(rust_pass);
+    Pass *pass = unwrap(rust_pass);
     PassManagerBase *pm = unwrap(PM);
     pm->add(pass);
 }
@@ -162,17 +170,99 @@
     return (Bits & FeatureEntry->Value) == FeatureEntry->Value;
 }
 
+enum class LLVMRustCodeModel {
+    Other,
+    Default,
+    JITDefault,
+    Small,
+    Kernel,
+    Medium,
+    Large,
+};
+
+static CodeModel::Model
+from_rust(LLVMRustCodeModel model)
+{
+    switch (model) {
+    case LLVMRustCodeModel::Default:
+        return CodeModel::Default;
+    case LLVMRustCodeModel::JITDefault:
+        return CodeModel::JITDefault;
+    case LLVMRustCodeModel::Small:
+        return CodeModel::Small;
+    case LLVMRustCodeModel::Kernel:
+        return CodeModel::Kernel;
+    case LLVMRustCodeModel::Medium:
+        return CodeModel::Medium;
+    case LLVMRustCodeModel::Large:
+        return CodeModel::Large;
+    default:
+        llvm_unreachable("Bad CodeModel.");
+  }
+}
+
+enum class LLVMRustCodeGenOptLevel {
+    Other,
+    None,
+    Less,
+    Default,
+    Aggressive,
+};
+
+static CodeGenOpt::Level
+from_rust(LLVMRustCodeGenOptLevel level)
+{
+    switch (level) {
+    case LLVMRustCodeGenOptLevel::None:
+        return CodeGenOpt::None;
+    case LLVMRustCodeGenOptLevel::Less:
+        return CodeGenOpt::Less;
+    case LLVMRustCodeGenOptLevel::Default:
+        return CodeGenOpt::Default;
+    case LLVMRustCodeGenOptLevel::Aggressive:
+        return CodeGenOpt::Aggressive;
+    default:
+        llvm_unreachable("Bad CodeGenOptLevel.");
+  }
+}
+
 extern "C" LLVMTargetMachineRef
 LLVMRustCreateTargetMachine(const char *triple,
                             const char *cpu,
                             const char *feature,
-                            CodeModel::Model CM,
-                            Reloc::Model RM,
-                            CodeGenOpt::Level OptLevel,
+                            LLVMRustCodeModel rust_CM,
+                            LLVMRelocMode Reloc,
+                            LLVMRustCodeGenOptLevel rust_OptLevel,
                             bool UseSoftFloat,
                             bool PositionIndependentExecutable,
                             bool FunctionSections,
                             bool DataSections) {
+
+#if LLVM_VERSION_MINOR <= 8
+    Reloc::Model RM;
+#else
+    Optional<Reloc::Model> RM;
+#endif
+    auto CM = from_rust(rust_CM);
+    auto OptLevel = from_rust(rust_OptLevel);
+
+    switch (Reloc){
+        case LLVMRelocStatic:
+            RM = Reloc::Static;
+            break;
+        case LLVMRelocPIC:
+            RM = Reloc::PIC_;
+            break;
+        case LLVMRelocDynamicNoPic:
+            RM = Reloc::DynamicNoPIC;
+            break;
+        default:
+#if LLVM_VERSION_MINOR <= 8
+            RM = Reloc::Default;
+#endif
+            break;
+    }
+
     std::string Error;
     Triple Trip(Triple::normalize(triple));
     const llvm::Target *TheTarget = TargetRegistry::lookupTarget(Trip.getTriple(),
@@ -188,7 +278,10 @@
     }
 
     TargetOptions Options;
+#if LLVM_VERSION_MINOR <= 8
     Options.PositionIndependentExecutable = PositionIndependentExecutable;
+#endif
+
     Options.FloatABIType = FloatABI::Default;
     if (UseSoftFloat) {
         Options.FloatABIType = FloatABI::Soft;
@@ -225,14 +318,14 @@
 
 extern "C" void
 LLVMRustConfigurePassManagerBuilder(LLVMPassManagerBuilderRef PMB,
-                                    CodeGenOpt::Level OptLevel,
+				    LLVMRustCodeGenOptLevel OptLevel,
                                     bool MergeFunctions,
                                     bool SLPVectorize,
                                     bool LoopVectorize) {
     // Ignore mergefunc for now as enabling it causes crashes.
     //unwrap(PMB)->MergeFunctions = MergeFunctions;
     unwrap(PMB)->SLPVectorize = SLPVectorize;
-    unwrap(PMB)->OptLevel = OptLevel;
+    unwrap(PMB)->OptLevel = from_rust(OptLevel);
     unwrap(PMB)->LoopVectorize = LoopVectorize;
 }
 
@@ -267,12 +360,19 @@
 // similar code in clang's BackendUtil.cpp file.
 extern "C" void
 LLVMRustRunFunctionPassManager(LLVMPassManagerRef PM, LLVMModuleRef M) {
-    FunctionPassManager *P = unwrap<FunctionPassManager>(PM);
+    llvm::legacy::FunctionPassManager *P = unwrap<llvm::legacy::FunctionPassManager>(PM);
     P->doInitialization();
+
+    // Upgrade all calls to old intrinsics first.
+    for (Module::iterator I = unwrap(M)->begin(),
+         E = unwrap(M)->end(); I != E;)
+        UpgradeCallsToIntrinsic(&*I++); // must be post-increment, as we remove
+
     for (Module::iterator I = unwrap(M)->begin(),
          E = unwrap(M)->end(); I != E; ++I)
         if (!I->isDeclaration())
             P->run(*I);
+
     P->doFinalization();
 }
 
@@ -288,13 +388,33 @@
     cl::ParseCommandLineOptions(Argc, Argv);
 }
 
-extern "C" bool
+enum class LLVMRustFileType {
+    Other,
+    AssemblyFile,
+    ObjectFile,
+};
+
+static TargetMachine::CodeGenFileType
+from_rust(LLVMRustFileType type)
+{
+    switch (type) {
+    case LLVMRustFileType::AssemblyFile:
+        return TargetMachine::CGFT_AssemblyFile;
+    case LLVMRustFileType::ObjectFile:
+        return TargetMachine::CGFT_ObjectFile;
+    default:
+        llvm_unreachable("Bad FileType.");
+  }
+}
+
+extern "C" LLVMRustResult
 LLVMRustWriteOutputFile(LLVMTargetMachineRef Target,
                         LLVMPassManagerRef PMR,
                         LLVMModuleRef M,
                         const char *path,
-                        TargetMachine::CodeGenFileType FileType) {
-  PassManager *PM = unwrap<PassManager>(PMR);
+                        LLVMRustFileType rust_FileType) {
+  llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR);
+  auto FileType = from_rust(rust_FileType);
 
   std::string ErrorInfo;
   std::error_code EC;
@@ -303,7 +423,7 @@
     ErrorInfo = EC.message();
   if (ErrorInfo != "") {
     LLVMRustSetLastError(ErrorInfo.c_str());
-    return false;
+    return LLVMRustResult::Failure;
   }
 
   unwrap(Target)->addPassesToEmitFile(*PM, OS, FileType, false);
@@ -313,14 +433,14 @@
   // stream (OS), so the only real safe place to delete this is here? Don't we
   // wish this was written in Rust?
   delete PM;
-  return true;
+  return LLVMRustResult::Success;
 }
 
 extern "C" void
 LLVMRustPrintModule(LLVMPassManagerRef PMR,
                     LLVMModuleRef M,
                     const char* path) {
-  PassManager *PM = unwrap<PassManager>(PMR);
+  llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR);
   std::string ErrorInfo;
 
   std::error_code EC;
@@ -358,9 +478,24 @@
 
 extern "C" void
 LLVMRustRunRestrictionPass(LLVMModuleRef M, char **symbols, size_t len) {
-    PassManager passes;
+    llvm::legacy::PassManager passes;
+
+#if LLVM_VERSION_MINOR <= 8
     ArrayRef<const char*> ref(symbols, len);
     passes.add(llvm::createInternalizePass(ref));
+#else
+    auto PreserveFunctions = [=](const GlobalValue &GV) {
+        for (size_t i=0; i<len; i++) {
+            if (GV.getName() == symbols[i]) {
+                return true;
+            }
+        }
+        return false;
+    };
+
+    passes.add(llvm::createInternalizePass(PreserveFunctions));
+#endif
+
     passes.run(*unwrap(M));
 }
 
@@ -396,3 +531,10 @@
 LLVMRustGetModuleDataLayout(LLVMModuleRef M) {
     return wrap(&unwrap(M)->getDataLayout());
 }
+
+extern "C" void
+LLVMRustSetModulePIELevel(LLVMModuleRef M) {
+#if LLVM_VERSION_MINOR >= 9
+    unwrap(M)->setPIELevel(PIELevel::Level::Large);
+#endif
+}
diff --git a/src/rustllvm/README b/src/rustllvm/README
index c0db3f6..e1c6dd0 100644
--- a/src/rustllvm/README
+++ b/src/rustllvm/README
@@ -1,2 +1,16 @@
 This directory currently contains some LLVM support code. This will generally
 be sent upstream to LLVM in time; for now it lives here.
+
+NOTE: the LLVM C++ ABI is subject to between-version breakage and must *never*
+be exposed to Rust. To allow for easy auditing of that, all Rust-exposed types
+must be typedef-ed as "LLVMXyz", or "LLVMRustXyz" if they were defined here.
+
+Functions that return a failure status and leave the error in
+the LLVM last error should return an LLVMRustResult rather than an
+int or anything to avoid confusion.
+
+When translating enums, add a single `Other` variant as the first
+one to allow for new variants to be added. It should abort when used
+as an input.
+
+All other types must not be typedef-ed as such.
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index fadd95c..0da25e7 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -13,6 +13,7 @@
 #include "llvm/Object/ObjectFile.h"
 #include "llvm/IR/DiagnosticInfo.h"
 #include "llvm/IR/DiagnosticPrinter.h"
+#include "llvm/IR/Instructions.h"
 
 #include "llvm/IR/CallSite.h"
 
@@ -27,6 +28,30 @@
 using namespace llvm::sys;
 using namespace llvm::object;
 
+// LLVMAtomicOrdering is already an enum - don't create another
+// one.
+static AtomicOrdering from_rust(LLVMAtomicOrdering Ordering) {
+  switch (Ordering) {
+    case LLVMAtomicOrderingNotAtomic:
+        return AtomicOrdering::NotAtomic;
+    case LLVMAtomicOrderingUnordered:
+        return AtomicOrdering::Unordered;
+    case LLVMAtomicOrderingMonotonic:
+        return AtomicOrdering::Monotonic;
+    case LLVMAtomicOrderingAcquire:
+        return AtomicOrdering::Acquire;
+    case LLVMAtomicOrderingRelease:
+        return AtomicOrdering::Release;
+    case LLVMAtomicOrderingAcquireRelease:
+        return AtomicOrdering::AcquireRelease;
+    case LLVMAtomicOrderingSequentiallyConsistent:
+        return AtomicOrdering::SequentiallyConsistent;
+  }
+
+  llvm_unreachable("Invalid LLVMAtomicOrdering value!");
+}
+
+
 static char *LastError;
 
 extern "C" LLVMMemoryBufferRef
@@ -57,49 +82,34 @@
     unwrap(M)->setTargetTriple(Triple::normalize(triple));
 }
 
-extern "C" LLVMValueRef LLVMRustConstSmallInt(LLVMTypeRef IntTy, unsigned N,
-                                              LLVMBool SignExtend) {
-  return LLVMConstInt(IntTy, (unsigned long long)N, SignExtend);
-}
-
-extern "C" LLVMValueRef LLVMRustConstInt(LLVMTypeRef IntTy,
-           unsigned N_hi,
-           unsigned N_lo,
-           LLVMBool SignExtend) {
-  unsigned long long N = N_hi;
-  N <<= 32;
-  N |= N_lo;
-  return LLVMConstInt(IntTy, N, SignExtend);
-}
-
 extern "C" void LLVMRustPrintPassTimings() {
   raw_fd_ostream OS (2, false); // stderr.
   TimerGroup::printAll(OS);
 }
 
-extern "C" LLVMValueRef LLVMGetNamedValue(LLVMModuleRef M,
-                                          const char* Name) {
+extern "C" LLVMValueRef LLVMRustGetNamedValue(LLVMModuleRef M,
+					      const char* Name) {
     return wrap(unwrap(M)->getNamedValue(Name));
 }
 
-extern "C" LLVMValueRef LLVMGetOrInsertFunction(LLVMModuleRef M,
-                                                const char* Name,
-                                                LLVMTypeRef FunctionTy) {
+extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M,
+						    const char* Name,
+						    LLVMTypeRef FunctionTy) {
   return wrap(unwrap(M)->getOrInsertFunction(Name,
                                              unwrap<FunctionType>(FunctionTy)));
 }
 
-extern "C" LLVMValueRef LLVMGetOrInsertGlobal(LLVMModuleRef M,
-                                              const char* Name,
-                                              LLVMTypeRef Ty) {
+extern "C" LLVMValueRef LLVMRustGetOrInsertGlobal(LLVMModuleRef M,
+						  const char* Name,
+						  LLVMTypeRef Ty) {
   return wrap(unwrap(M)->getOrInsertGlobal(Name, unwrap(Ty)));
 }
 
-extern "C" LLVMTypeRef LLVMMetadataTypeInContext(LLVMContextRef C) {
+extern "C" LLVMTypeRef LLVMRustMetadataTypeInContext(LLVMContextRef C) {
   return wrap(Type::getMetadataTy(*unwrap(C)));
 }
 
-extern "C" void LLVMAddCallSiteAttribute(LLVMValueRef Instr, unsigned index, uint64_t Val) {
+extern "C" void LLVMRustAddCallSiteAttribute(LLVMValueRef Instr, unsigned index, uint64_t Val) {
   CallSite Call = CallSite(unwrap<Instruction>(Instr));
   AttrBuilder B;
   B.addRawValue(Val);
@@ -110,7 +120,10 @@
 }
 
 
-extern "C" void LLVMAddDereferenceableCallSiteAttr(LLVMValueRef Instr, unsigned idx, uint64_t b) {
+extern "C" void LLVMRustAddDereferenceableCallSiteAttr(LLVMValueRef Instr,
+						       unsigned idx,
+						       uint64_t b)
+{
   CallSite Call = CallSite(unwrap<Instruction>(Instr));
   AttrBuilder B;
   B.addDereferenceableAttr(b);
@@ -120,38 +133,50 @@
                                                          idx, B)));
 }
 
-extern "C" void LLVMAddFunctionAttribute(LLVMValueRef Fn, unsigned index,
-                                         uint64_t Val) {
+extern "C" void LLVMRustAddFunctionAttribute(LLVMValueRef Fn,
+					     unsigned index,
+					     uint64_t Val)
+{
   Function *A = unwrap<Function>(Fn);
   AttrBuilder B;
   B.addRawValue(Val);
   A->addAttributes(index, AttributeSet::get(A->getContext(), index, B));
 }
 
-extern "C" void LLVMAddDereferenceableAttr(LLVMValueRef Fn, unsigned index, uint64_t bytes) {
+extern "C" void LLVMRustAddDereferenceableAttr(LLVMValueRef Fn,
+					       unsigned index,
+					       uint64_t bytes)
+{
   Function *A = unwrap<Function>(Fn);
   AttrBuilder B;
   B.addDereferenceableAttr(bytes);
   A->addAttributes(index, AttributeSet::get(A->getContext(), index, B));
 }
 
-extern "C" void LLVMAddFunctionAttrString(LLVMValueRef Fn, unsigned index, const char *Name) {
+extern "C" void LLVMRustAddFunctionAttrString(LLVMValueRef Fn,
+					      unsigned index,
+					      const char *Name)
+{
   Function *F = unwrap<Function>(Fn);
   AttrBuilder B;
   B.addAttribute(Name);
   F->addAttributes(index, AttributeSet::get(F->getContext(), index, B));
 }
 
-extern "C" void LLVMAddFunctionAttrStringValue(LLVMValueRef Fn, unsigned index,
-                                               const char *Name,
-                                               const char *Value) {
+extern "C" void LLVMRustAddFunctionAttrStringValue(LLVMValueRef Fn,
+						   unsigned index,
+						   const char *Name,
+						   const char *Value) {
   Function *F = unwrap<Function>(Fn);
   AttrBuilder B;
   B.addAttribute(Name, Value);
   F->addAttributes(index, AttributeSet::get(F->getContext(), index, B));
 }
 
-extern "C" void LLVMRemoveFunctionAttributes(LLVMValueRef Fn, unsigned index, uint64_t Val) {
+extern "C" void LLVMRustRemoveFunctionAttributes(LLVMValueRef Fn,
+						 unsigned index,
+						 uint64_t Val)
+{
   Function *A = unwrap<Function>(Fn);
   const AttributeSet PAL = A->getAttributes();
   AttrBuilder B(Val);
@@ -161,7 +186,10 @@
   A->setAttributes(PALnew);
 }
 
-extern "C" void LLVMRemoveFunctionAttrString(LLVMValueRef fn, unsigned index, const char *Name) {
+extern "C" void LLVMRustRemoveFunctionAttrString(LLVMValueRef fn,
+						 unsigned index,
+						 const char *Name)
+{
   Function *f = unwrap<Function>(fn);
   LLVMContext &C = f->getContext();
   AttrBuilder B;
@@ -181,80 +209,122 @@
     }
 }
 
-extern "C" LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef B,
-                                            LLVMValueRef source,
-                                            const char* Name,
-                                            AtomicOrdering order,
-                                            unsigned alignment) {
+extern "C" LLVMValueRef LLVMRustBuildAtomicLoad(LLVMBuilderRef B,
+						LLVMValueRef source,
+						const char* Name,
+						LLVMAtomicOrdering order,
+						unsigned alignment) {
     LoadInst* li = new LoadInst(unwrap(source),0);
-    li->setAtomic(order);
+    li->setAtomic(from_rust(order));
     li->setAlignment(alignment);
     return wrap(unwrap(B)->Insert(li, Name));
 }
 
-extern "C" LLVMValueRef LLVMBuildAtomicStore(LLVMBuilderRef B,
-                                             LLVMValueRef val,
-                                             LLVMValueRef target,
-                                             AtomicOrdering order,
-                                             unsigned alignment) {
+extern "C" LLVMValueRef LLVMRustBuildAtomicStore(LLVMBuilderRef B,
+						 LLVMValueRef val,
+						 LLVMValueRef target,
+						 LLVMAtomicOrdering order,
+						 unsigned alignment) {
     StoreInst* si = new StoreInst(unwrap(val),unwrap(target));
-    si->setAtomic(order);
+    si->setAtomic(from_rust(order));
     si->setAlignment(alignment);
     return wrap(unwrap(B)->Insert(si));
 }
 
-extern "C" LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef B,
+extern "C" LLVMValueRef LLVMRustBuildAtomicCmpXchg(LLVMBuilderRef B,
                                                LLVMValueRef target,
                                                LLVMValueRef old,
                                                LLVMValueRef source,
-                                               AtomicOrdering order,
-                                               AtomicOrdering failure_order,
+                                               LLVMAtomicOrdering order,
+                                               LLVMAtomicOrdering failure_order,
                                                LLVMBool weak) {
-    AtomicCmpXchgInst* acxi = unwrap(B)->CreateAtomicCmpXchg(unwrap(target),
-                                                             unwrap(old),
-                                                             unwrap(source),
-                                                             order,
-                                                             failure_order);
+    AtomicCmpXchgInst* acxi = unwrap(B)->CreateAtomicCmpXchg(
+        unwrap(target),
+        unwrap(old),
+        unwrap(source),
+        from_rust(order),
+	from_rust(failure_order));
     acxi->setWeak(weak);
     return wrap(acxi);
 }
-extern "C" LLVMValueRef LLVMBuildAtomicFence(LLVMBuilderRef B,
-                                             AtomicOrdering order,
-                                             SynchronizationScope scope) {
-    return wrap(unwrap(B)->CreateFence(order, scope));
+
+enum class LLVMRustSynchronizationScope {
+    Other,
+    SingleThread,
+    CrossThread,
+};
+
+static SynchronizationScope
+from_rust(LLVMRustSynchronizationScope scope)
+{
+    switch (scope) {
+    case LLVMRustSynchronizationScope::SingleThread:
+        return SingleThread;
+    case LLVMRustSynchronizationScope::CrossThread:
+        return CrossThread;
+    default:
+        llvm_unreachable("bad SynchronizationScope.");
+    }
 }
 
-extern "C" void LLVMSetDebug(int Enabled) {
+extern "C" LLVMValueRef LLVMRustBuildAtomicFence(
+    LLVMBuilderRef B,
+    LLVMAtomicOrdering order,
+    LLVMRustSynchronizationScope scope)
+{
+    return wrap(unwrap(B)->CreateFence(from_rust(order), from_rust(scope)));
+}
+
+extern "C" void LLVMRustSetDebug(int Enabled) {
 #ifndef NDEBUG
   DebugFlag = Enabled;
 #endif
 }
 
-extern "C" LLVMValueRef LLVMInlineAsm(LLVMTypeRef Ty,
-                                      char *AsmString,
-                                      char *Constraints,
-                                      LLVMBool HasSideEffects,
-                                      LLVMBool IsAlignStack,
-                                      unsigned Dialect) {
-    return wrap(InlineAsm::get(unwrap<FunctionType>(Ty), AsmString,
-                               Constraints, HasSideEffects,
-                               IsAlignStack, (InlineAsm::AsmDialect) Dialect));
+enum class LLVMRustAsmDialect {
+    Other,
+    Att,
+    Intel,
+};
+
+static InlineAsm::AsmDialect
+from_rust(LLVMRustAsmDialect dialect)
+{
+    switch (dialect) {
+    case LLVMRustAsmDialect::Att:
+        return InlineAsm::AD_ATT;
+    case LLVMRustAsmDialect::Intel:
+        return InlineAsm::AD_Intel;
+    default:
+        llvm_unreachable("bad AsmDialect.");
+    }
 }
 
-typedef DIBuilder* DIBuilderRef;
+extern "C" LLVMValueRef LLVMRustInlineAsm(LLVMTypeRef Ty,
+					  char *AsmString,
+					  char *Constraints,
+					  LLVMBool HasSideEffects,
+					  LLVMBool IsAlignStack,
+					  LLVMRustAsmDialect Dialect) {
+    return wrap(InlineAsm::get(unwrap<FunctionType>(Ty), AsmString,
+                               Constraints, HasSideEffects,
+                               IsAlignStack, from_rust(Dialect)));
+}
 
-typedef struct LLVMOpaqueMetadata *LLVMMetadataRef;
+typedef DIBuilder* LLVMRustDIBuilderRef;
+
+typedef struct LLVMOpaqueMetadata *LLVMRustMetadataRef;
 
 namespace llvm {
-DEFINE_ISA_CONVERSION_FUNCTIONS(Metadata, LLVMMetadataRef)
+DEFINE_ISA_CONVERSION_FUNCTIONS(Metadata, LLVMRustMetadataRef)
 
-inline Metadata **unwrap(LLVMMetadataRef *Vals) {
+inline Metadata **unwrap(LLVMRustMetadataRef *Vals) {
   return reinterpret_cast<Metadata**>(Vals);
 }
 }
 
 template<typename DIT>
-DIT* unwrapDIptr(LLVMMetadataRef ref) {
+DIT* unwrapDIptr(LLVMRustMetadataRef ref) {
     return (DIT*) (ref ? unwrap<MDNode>(ref) : NULL);
 }
 
@@ -266,11 +336,11 @@
     return DEBUG_METADATA_VERSION;
 }
 
-extern "C" uint32_t LLVMVersionMinor() {
+extern "C" uint32_t LLVMRustVersionMinor() {
   return LLVM_VERSION_MINOR;
 }
 
-extern "C" uint32_t LLVMVersionMajor() {
+extern "C" uint32_t LLVMRustVersionMajor() {
   return LLVM_VERSION_MAJOR;
 }
 
@@ -280,20 +350,20 @@
     unwrap(M)->addModuleFlag(Module::Warning, name, value);
 }
 
-extern "C" DIBuilderRef LLVMDIBuilderCreate(LLVMModuleRef M) {
+extern "C" LLVMRustDIBuilderRef LLVMRustDIBuilderCreate(LLVMModuleRef M) {
     return new DIBuilder(*unwrap(M));
 }
 
-extern "C" void LLVMDIBuilderDispose(DIBuilderRef Builder) {
+extern "C" void LLVMRustDIBuilderDispose(LLVMRustDIBuilderRef Builder) {
     delete Builder;
 }
 
-extern "C" void LLVMDIBuilderFinalize(DIBuilderRef Builder) {
+extern "C" void LLVMRustDIBuilderFinalize(LLVMRustDIBuilderRef Builder) {
     Builder->finalize();
 }
 
-extern "C" LLVMMetadataRef LLVMDIBuilderCreateCompileUnit(
-    DIBuilderRef Builder,
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateCompileUnit(
+    LLVMRustDIBuilderRef Builder,
     unsigned Lang,
     const char* File,
     const char* Dir,
@@ -312,17 +382,17 @@
                                            SplitName));
 }
 
-extern "C" LLVMMetadataRef LLVMDIBuilderCreateFile(
-    DIBuilderRef Builder,
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateFile(
+    LLVMRustDIBuilderRef Builder,
     const char* Filename,
     const char* Directory) {
     return wrap(Builder->createFile(Filename, Directory));
 }
 
-extern "C" LLVMMetadataRef LLVMDIBuilderCreateSubroutineType(
-    DIBuilderRef Builder,
-    LLVMMetadataRef File,
-    LLVMMetadataRef ParameterTypes) {
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateSubroutineType(
+    LLVMRustDIBuilderRef Builder,
+    LLVMRustMetadataRef File,
+    LLVMRustMetadataRef ParameterTypes) {
     return wrap(Builder->createSubroutineType(
 #if LLVM_VERSION_MINOR == 7
         unwrapDI<DIFile>(File),
@@ -330,22 +400,22 @@
         DITypeRefArray(unwrap<MDTuple>(ParameterTypes))));
 }
 
-extern "C" LLVMMetadataRef LLVMDIBuilderCreateFunction(
-    DIBuilderRef Builder,
-    LLVMMetadataRef Scope,
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateFunction(
+    LLVMRustDIBuilderRef Builder,
+    LLVMRustMetadataRef Scope,
     const char* Name,
     const char* LinkageName,
-    LLVMMetadataRef File,
+    LLVMRustMetadataRef File,
     unsigned LineNo,
-    LLVMMetadataRef Ty,
+    LLVMRustMetadataRef Ty,
     bool isLocalToUnit,
     bool isDefinition,
     unsigned ScopeLine,
     unsigned Flags,
     bool isOptimized,
     LLVMValueRef Fn,
-    LLVMMetadataRef TParam,
-    LLVMMetadataRef Decl) {
+    LLVMRustMetadataRef TParam,
+    LLVMRustMetadataRef Decl) {
 #if LLVM_VERSION_MINOR >= 8
     DITemplateParameterArray TParams =
         DITemplateParameterArray(unwrap<MDTuple>(TParam));
@@ -370,8 +440,8 @@
 #endif
 }
 
-extern "C" LLVMMetadataRef LLVMDIBuilderCreateBasicType(
-    DIBuilderRef Builder,
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateBasicType(
+    LLVMRustDIBuilderRef Builder,
     const char* Name,
     uint64_t SizeInBits,
     uint64_t AlignInBits,
@@ -381,9 +451,9 @@
         AlignInBits, Encoding));
 }
 
-extern "C" LLVMMetadataRef LLVMDIBuilderCreatePointerType(
-    DIBuilderRef Builder,
-    LLVMMetadataRef PointeeTy,
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreatePointerType(
+    LLVMRustDIBuilderRef Builder,
+    LLVMRustMetadataRef PointeeTy,
     uint64_t SizeInBits,
     uint64_t AlignInBits,
     const char* Name) {
@@ -391,19 +461,19 @@
         unwrapDI<DIType>(PointeeTy), SizeInBits, AlignInBits, Name));
 }
 
-extern "C" LLVMMetadataRef LLVMDIBuilderCreateStructType(
-    DIBuilderRef Builder,
-    LLVMMetadataRef Scope,
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateStructType(
+    LLVMRustDIBuilderRef Builder,
+    LLVMRustMetadataRef Scope,
     const char* Name,
-    LLVMMetadataRef File,
+    LLVMRustMetadataRef File,
     unsigned LineNumber,
     uint64_t SizeInBits,
     uint64_t AlignInBits,
     unsigned Flags,
-    LLVMMetadataRef DerivedFrom,
-    LLVMMetadataRef Elements,
+    LLVMRustMetadataRef DerivedFrom,
+    LLVMRustMetadataRef Elements,
     unsigned RunTimeLang,
-    LLVMMetadataRef VTableHolder,
+    LLVMRustMetadataRef VTableHolder,
     const char *UniqueId) {
     return wrap(Builder->createStructType(
         unwrapDI<DIDescriptor>(Scope),
@@ -421,17 +491,17 @@
         ));
 }
 
-extern "C" LLVMMetadataRef LLVMDIBuilderCreateMemberType(
-    DIBuilderRef Builder,
-    LLVMMetadataRef Scope,
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateMemberType(
+    LLVMRustDIBuilderRef Builder,
+    LLVMRustMetadataRef Scope,
     const char* Name,
-    LLVMMetadataRef File,
+    LLVMRustMetadataRef File,
     unsigned LineNo,
     uint64_t SizeInBits,
     uint64_t AlignInBits,
     uint64_t OffsetInBits,
     unsigned Flags,
-    LLVMMetadataRef Ty) {
+    LLVMRustMetadataRef Ty) {
     return wrap(Builder->createMemberType(
         unwrapDI<DIDescriptor>(Scope), Name,
         unwrapDI<DIFile>(File), LineNo,
@@ -439,10 +509,10 @@
         unwrapDI<DIType>(Ty)));
 }
 
-extern "C" LLVMMetadataRef LLVMDIBuilderCreateLexicalBlock(
-    DIBuilderRef Builder,
-    LLVMMetadataRef Scope,
-    LLVMMetadataRef File,
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateLexicalBlock(
+    LLVMRustDIBuilderRef Builder,
+    LLVMRustMetadataRef Scope,
+    LLVMRustMetadataRef File,
     unsigned Line,
     unsigned Col) {
     return wrap(Builder->createLexicalBlock(
@@ -451,17 +521,17 @@
         ));
 }
 
-extern "C" LLVMMetadataRef LLVMDIBuilderCreateStaticVariable(
-    DIBuilderRef Builder,
-    LLVMMetadataRef Context,
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateStaticVariable(
+    LLVMRustDIBuilderRef Builder,
+    LLVMRustMetadataRef Context,
     const char* Name,
     const char* LinkageName,
-    LLVMMetadataRef File,
+    LLVMRustMetadataRef File,
     unsigned LineNo,
-    LLVMMetadataRef Ty,
+    LLVMRustMetadataRef Ty,
     bool isLocalToUnit,
     LLVMValueRef Val,
-    LLVMMetadataRef Decl = NULL) {
+    LLVMRustMetadataRef Decl = NULL) {
     return wrap(Builder->createGlobalVariable(unwrapDI<DIDescriptor>(Context),
         Name,
         LinkageName,
@@ -473,14 +543,14 @@
         unwrapDIptr<MDNode>(Decl)));
 }
 
-extern "C" LLVMMetadataRef LLVMDIBuilderCreateVariable(
-    DIBuilderRef Builder,
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateVariable(
+    LLVMRustDIBuilderRef Builder,
     unsigned Tag,
-    LLVMMetadataRef Scope,
+    LLVMRustMetadataRef Scope,
     const char* Name,
-    LLVMMetadataRef File,
+    LLVMRustMetadataRef File,
     unsigned LineNo,
-    LLVMMetadataRef Ty,
+    LLVMRustMetadataRef Ty,
     bool AlwaysPreserve,
     unsigned Flags,
     int64_t* AddrOps,
@@ -509,50 +579,50 @@
 #endif
 }
 
-extern "C" LLVMMetadataRef LLVMDIBuilderCreateArrayType(
-    DIBuilderRef Builder,
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateArrayType(
+    LLVMRustDIBuilderRef Builder,
     uint64_t Size,
     uint64_t AlignInBits,
-    LLVMMetadataRef Ty,
-    LLVMMetadataRef Subscripts) {
+    LLVMRustMetadataRef Ty,
+    LLVMRustMetadataRef Subscripts) {
     return wrap(Builder->createArrayType(Size, AlignInBits,
         unwrapDI<DIType>(Ty),
         DINodeArray(unwrapDI<MDTuple>(Subscripts))
     ));
 }
 
-extern "C" LLVMMetadataRef LLVMDIBuilderCreateVectorType(
-    DIBuilderRef Builder,
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateVectorType(
+    LLVMRustDIBuilderRef Builder,
     uint64_t Size,
     uint64_t AlignInBits,
-    LLVMMetadataRef Ty,
-    LLVMMetadataRef Subscripts) {
+    LLVMRustMetadataRef Ty,
+    LLVMRustMetadataRef Subscripts) {
     return wrap(Builder->createVectorType(Size, AlignInBits,
         unwrapDI<DIType>(Ty),
         DINodeArray(unwrapDI<MDTuple>(Subscripts))
     ));
 }
 
-extern "C" LLVMMetadataRef LLVMDIBuilderGetOrCreateSubrange(
-    DIBuilderRef Builder,
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderGetOrCreateSubrange(
+    LLVMRustDIBuilderRef Builder,
     int64_t Lo,
     int64_t Count) {
     return wrap(Builder->getOrCreateSubrange(Lo, Count));
 }
 
-extern "C" LLVMMetadataRef LLVMDIBuilderGetOrCreateArray(
-    DIBuilderRef Builder,
-    LLVMMetadataRef* Ptr,
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderGetOrCreateArray(
+    LLVMRustDIBuilderRef Builder,
+    LLVMRustMetadataRef* Ptr,
     unsigned Count) {
     Metadata **DataValue = unwrap(Ptr);
     return wrap(Builder->getOrCreateArray(
         ArrayRef<Metadata*>(DataValue, Count)).get());
 }
 
-extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd(
-    DIBuilderRef Builder,
+extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd(
+    LLVMRustDIBuilderRef Builder,
     LLVMValueRef Val,
-    LLVMMetadataRef VarInfo,
+    LLVMRustMetadataRef VarInfo,
     int64_t* AddrOps,
     unsigned AddrOpsCount,
     LLVMValueRef DL,
@@ -566,10 +636,10 @@
         unwrap(InsertAtEnd)));
 }
 
-extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareBefore(
-    DIBuilderRef Builder,
+extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareBefore(
+    LLVMRustDIBuilderRef Builder,
     LLVMValueRef Val,
-    LLVMMetadataRef VarInfo,
+    LLVMRustMetadataRef VarInfo,
     int64_t* AddrOps,
     unsigned AddrOpsCount,
     LLVMValueRef DL,
@@ -583,24 +653,24 @@
         unwrap<Instruction>(InsertBefore)));
 }
 
-extern "C" LLVMMetadataRef LLVMDIBuilderCreateEnumerator(
-    DIBuilderRef Builder,
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateEnumerator(
+    LLVMRustDIBuilderRef Builder,
     const char* Name,
     uint64_t Val)
 {
     return wrap(Builder->createEnumerator(Name, Val));
 }
 
-extern "C" LLVMMetadataRef LLVMDIBuilderCreateEnumerationType(
-    DIBuilderRef Builder,
-    LLVMMetadataRef Scope,
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateEnumerationType(
+    LLVMRustDIBuilderRef Builder,
+    LLVMRustMetadataRef Scope,
     const char* Name,
-    LLVMMetadataRef File,
+    LLVMRustMetadataRef File,
     unsigned LineNumber,
     uint64_t SizeInBits,
     uint64_t AlignInBits,
-    LLVMMetadataRef Elements,
-    LLVMMetadataRef ClassType)
+    LLVMRustMetadataRef Elements,
+    LLVMRustMetadataRef ClassType)
 {
     return wrap(Builder->createEnumerationType(
         unwrapDI<DIDescriptor>(Scope),
@@ -613,16 +683,16 @@
         unwrapDI<DIType>(ClassType)));
 }
 
-extern "C" LLVMMetadataRef LLVMDIBuilderCreateUnionType(
-    DIBuilderRef Builder,
-    LLVMMetadataRef Scope,
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateUnionType(
+    LLVMRustDIBuilderRef Builder,
+    LLVMRustMetadataRef Scope,
     const char* Name,
-    LLVMMetadataRef File,
+    LLVMRustMetadataRef File,
     unsigned LineNumber,
     uint64_t SizeInBits,
     uint64_t AlignInBits,
     unsigned Flags,
-    LLVMMetadataRef Elements,
+    LLVMRustMetadataRef Elements,
     unsigned RunTimeLang,
     const char* UniqueId)
 {
@@ -640,12 +710,12 @@
         ));
 }
 
-extern "C" LLVMMetadataRef LLVMDIBuilderCreateTemplateTypeParameter(
-    DIBuilderRef Builder,
-    LLVMMetadataRef Scope,
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter(
+    LLVMRustDIBuilderRef Builder,
+    LLVMRustMetadataRef Scope,
     const char* Name,
-    LLVMMetadataRef Ty,
-    LLVMMetadataRef File,
+    LLVMRustMetadataRef Ty,
+    LLVMRustMetadataRef File,
     unsigned LineNo,
     unsigned ColumnNo)
 {
@@ -656,21 +726,11 @@
       ));
 }
 
-extern "C" int64_t LLVMDIBuilderCreateOpDeref()
-{
-    return dwarf::DW_OP_deref;
-}
-
-extern "C" int64_t LLVMDIBuilderCreateOpPlus()
-{
-    return dwarf::DW_OP_plus;
-}
-
-extern "C" LLVMMetadataRef LLVMDIBuilderCreateNameSpace(
-    DIBuilderRef Builder,
-    LLVMMetadataRef Scope,
+extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateNameSpace(
+    LLVMRustDIBuilderRef Builder,
+    LLVMRustMetadataRef Scope,
     const char* Name,
-    LLVMMetadataRef File,
+    LLVMRustMetadataRef File,
     unsigned LineNo)
 {
     return wrap(Builder->createNameSpace(
@@ -680,22 +740,22 @@
         LineNo));
 }
 
-extern "C" void LLVMDICompositeTypeSetTypeArray(
-    DIBuilderRef Builder,
-    LLVMMetadataRef CompositeType,
-    LLVMMetadataRef TypeArray)
+extern "C" void LLVMRustDICompositeTypeSetTypeArray(
+    LLVMRustDIBuilderRef Builder,
+    LLVMRustMetadataRef CompositeType,
+    LLVMRustMetadataRef TypeArray)
 {
     DICompositeType *tmp = unwrapDI<DICompositeType>(CompositeType);
     Builder->replaceArrays(tmp, DINodeArray(unwrap<MDTuple>(TypeArray)));
 }
 
-extern "C" LLVMValueRef LLVMDIBuilderCreateDebugLocation(
+extern "C" LLVMValueRef LLVMRustDIBuilderCreateDebugLocation(
   LLVMContextRef Context,
   unsigned Line,
   unsigned Column,
-  LLVMMetadataRef Scope,
-  LLVMMetadataRef InlinedAt) {
-
+  LLVMRustMetadataRef Scope,
+  LLVMRustMetadataRef InlinedAt)
+{
     LLVMContext& context = *unwrap(Context);
 
     DebugLoc debug_loc = DebugLoc::get(Line,
@@ -706,12 +766,22 @@
     return wrap(MetadataAsValue::get(context, debug_loc.getAsMDNode()));
 }
 
-extern "C" void LLVMWriteTypeToString(LLVMTypeRef Type, RustStringRef str) {
+extern "C" int64_t LLVMRustDIBuilderCreateOpDeref()
+{
+    return dwarf::DW_OP_deref;
+}
+
+extern "C" int64_t LLVMRustDIBuilderCreateOpPlus()
+{
+    return dwarf::DW_OP_plus;
+}
+
+extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Type, RustStringRef str) {
     raw_rust_string_ostream os(str);
     unwrap<llvm::Type>(Type)->print(os);
 }
 
-extern "C" void LLVMWriteValueToString(LLVMValueRef Value, RustStringRef str) {
+extern "C" void LLVMRustWriteValueToString(LLVMValueRef Value, RustStringRef str) {
     raw_rust_string_ostream os(str);
     os << "(";
     unwrap<llvm::Value>(Value)->getType()->print(os);
@@ -746,13 +816,6 @@
     return true;
 }
 
-extern "C" void
-LLVMRustSetDLLStorageClass(LLVMValueRef Value,
-                           GlobalValue::DLLStorageClassTypes Class) {
-    GlobalValue *V = unwrap<GlobalValue>(Value);
-    V->setDLLStorageClass(Class);
-}
-
 // Note that the two following functions look quite similar to the
 // LLVMGetSectionName function. Sadly, it appears that this function only
 // returns a char* pointer, which isn't guaranteed to be null-terminated. The
@@ -768,7 +831,7 @@
     return reinterpret_cast<section_iterator*>(SI);
 }
 
-extern "C" int
+extern "C" size_t
 LLVMRustGetSectionName(LLVMSectionIteratorRef SI, const char **ptr) {
     StringRef ret;
     if (std::error_code ec = (*unwrap(SI))->getName(ret))
@@ -787,13 +850,13 @@
 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DebugLoc, LLVMDebugLocRef)
 
 extern "C" void
-LLVMWriteTwineToString(LLVMTwineRef T, RustStringRef str) {
+LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef str) {
     raw_rust_string_ostream os(str);
     unwrap(T)->print(os);
 }
 
 extern "C" void
-LLVMUnpackOptimizationDiagnostic(
+LLVMRustUnpackOptimizationDiagnostic(
     LLVMDiagnosticInfoRef di,
     const char **pass_name_out,
     LLVMValueRef *function_out,
@@ -811,7 +874,7 @@
 }
 
 extern "C" void
-LLVMUnpackInlineAsmDiagnostic(
+LLVMRustUnpackInlineAsmDiagnostic(
     LLVMDiagnosticInfoRef di,
     unsigned *cookie_out,
     LLVMTwineRef *message_out,
@@ -826,17 +889,111 @@
     *instruction_out = wrap(ia->getInstruction());
 }
 
-extern "C" void LLVMWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef di, RustStringRef str) {
+extern "C" void LLVMRustWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef di, RustStringRef str) {
     raw_rust_string_ostream os(str);
     DiagnosticPrinterRawOStream dp(os);
     unwrap(di)->print(dp);
 }
 
-extern "C" int LLVMGetDiagInfoKind(LLVMDiagnosticInfoRef di) {
-    return unwrap(di)->getKind();
+enum class LLVMRustDiagnosticKind {
+    Other,
+    InlineAsm,
+    StackSize,
+    DebugMetadataVersion,
+    SampleProfile,
+    OptimizationRemark,
+    OptimizationRemarkMissed,
+    OptimizationRemarkAnalysis,
+    OptimizationRemarkAnalysisFPCommute,
+    OptimizationRemarkAnalysisAliasing,
+    OptimizationRemarkOther,
+    OptimizationFailure,
+};
+
+static LLVMRustDiagnosticKind
+to_rust(DiagnosticKind kind)
+{
+    switch (kind) {
+    case DK_InlineAsm:
+        return LLVMRustDiagnosticKind::InlineAsm;
+    case DK_StackSize:
+        return LLVMRustDiagnosticKind::StackSize;
+    case DK_DebugMetadataVersion:
+        return LLVMRustDiagnosticKind::DebugMetadataVersion;
+    case DK_SampleProfile:
+        return LLVMRustDiagnosticKind::SampleProfile;
+    case DK_OptimizationRemark:
+        return LLVMRustDiagnosticKind::OptimizationRemark;
+    case DK_OptimizationRemarkMissed:
+        return LLVMRustDiagnosticKind::OptimizationRemarkMissed;
+    case DK_OptimizationRemarkAnalysis:
+        return LLVMRustDiagnosticKind::OptimizationRemarkAnalysis;
+#if LLVM_VERSION_MINOR >= 8
+    case DK_OptimizationRemarkAnalysisFPCommute:
+        return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisFPCommute;
+    case DK_OptimizationRemarkAnalysisAliasing:
+        return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisAliasing;
+#endif
+    default:
+#if LLVM_VERSION_MINOR >= 9
+        return (kind >= DK_FirstRemark && kind <= DK_LastRemark) ?
+            LLVMRustDiagnosticKind::OptimizationRemarkOther :
+            LLVMRustDiagnosticKind::Other;
+#else
+        return LLVMRustDiagnosticKind::Other;
+#endif
+  }
 }
 
-extern "C" void LLVMWriteDebugLocToString(
+extern "C" LLVMRustDiagnosticKind LLVMRustGetDiagInfoKind(LLVMDiagnosticInfoRef di) {
+    return to_rust((DiagnosticKind) unwrap(di)->getKind());
+}
+// This is kept distinct from LLVMGetTypeKind, because when
+// a new type kind is added, the Rust-side enum must be
+// updated or UB will result.
+extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) {
+  switch (unwrap(Ty)->getTypeID()) {
+  case Type::VoidTyID:
+    return LLVMVoidTypeKind;
+  case Type::HalfTyID:
+    return LLVMHalfTypeKind;
+  case Type::FloatTyID:
+    return LLVMFloatTypeKind;
+  case Type::DoubleTyID:
+    return LLVMDoubleTypeKind;
+  case Type::X86_FP80TyID:
+    return LLVMX86_FP80TypeKind;
+  case Type::FP128TyID:
+    return LLVMFP128TypeKind;
+  case Type::PPC_FP128TyID:
+    return LLVMPPC_FP128TypeKind;
+  case Type::LabelTyID:
+    return LLVMLabelTypeKind;
+  case Type::MetadataTyID:
+    return LLVMMetadataTypeKind;
+  case Type::IntegerTyID:
+    return LLVMIntegerTypeKind;
+  case Type::FunctionTyID:
+    return LLVMFunctionTypeKind;
+  case Type::StructTyID:
+    return LLVMStructTypeKind;
+  case Type::ArrayTyID:
+    return LLVMArrayTypeKind;
+  case Type::PointerTyID:
+    return LLVMPointerTypeKind;
+  case Type::VectorTyID:
+    return LLVMVectorTypeKind;
+  case Type::X86_MMXTyID:
+    return LLVMX86_MMXTypeKind;
+#if LLVM_VERSION_MINOR >= 8
+  case Type::TokenTyID:
+    return LLVMTokenTypeKind;
+#endif
+  }
+  llvm_unreachable("Unhandled TypeID.");
+}
+
+extern "C" void LLVMRustWriteDebugLocToString(
     LLVMContextRef C,
     LLVMDebugLocRef dl,
     RustStringRef str)
@@ -847,7 +1004,7 @@
 
 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
 
-extern "C" void LLVMSetInlineAsmDiagnosticHandler(
+extern "C" void LLVMRustSetInlineAsmDiagnosticHandler(
     LLVMContextRef C,
     LLVMContext::InlineAsmDiagHandlerTy H,
     void *CX)
@@ -855,7 +1012,8 @@
     unwrap(C)->setInlineAsmDiagnosticHandler(H, CX);
 }
 
-extern "C" void LLVMWriteSMDiagnosticToString(LLVMSMDiagnosticRef d, RustStringRef str) {
+extern "C" void LLVMRustWriteSMDiagnosticToString(LLVMSMDiagnosticRef d,
+						  RustStringRef str) {
     raw_rust_string_ostream os(str);
     unwrap(d)->print("", os);
 }
diff --git a/src/rustllvm/llvm-auto-clean-trigger b/src/rustllvm/llvm-auto-clean-trigger
index 1953fc5..e871763 100644
--- a/src/rustllvm/llvm-auto-clean-trigger
+++ b/src/rustllvm/llvm-auto-clean-trigger
@@ -1,4 +1,4 @@
 # If this file is modified, then llvm will be forcibly cleaned and then rebuilt.
 # The actual contents of this file do not matter, but to trigger a change on the
 # build bots then the contents should be changed so git updates the mtime.
-2016-06-23
+2016-07-25b
diff --git a/src/rustllvm/rustllvm.h b/src/rustllvm/rustllvm.h
index 2a47e8b..5aae11f 100644
--- a/src/rustllvm/rustllvm.h
+++ b/src/rustllvm/rustllvm.h
@@ -58,6 +58,11 @@
 
 void LLVMRustSetLastError(const char*);
 
+enum class LLVMRustResult {
+    Success,
+    Failure
+};
+
 typedef struct OpaqueRustString *RustStringRef;
 typedef struct LLVMOpaqueTwine *LLVMTwineRef;
 typedef struct LLVMOpaqueDebugLoc *LLVMDebugLocRef;
diff --git a/src/test/compile-fail-fulldeps/lint-plugin-forbid-attrs.rs b/src/test/compile-fail-fulldeps/lint-plugin-forbid-attrs.rs
index 83c845b..61a8ee8 100644
--- a/src/test/compile-fail-fulldeps/lint-plugin-forbid-attrs.rs
+++ b/src/test/compile-fail-fulldeps/lint-plugin-forbid-attrs.rs
@@ -14,6 +14,8 @@
 #![feature(plugin)]
 #![plugin(lint_plugin_test)]
 #![forbid(test_lint)]
+//~^ NOTE lint level defined here
+//~| NOTE `forbid` lint level set here
 
 fn lintme() { } //~ ERROR item is named 'lintme'
 
diff --git a/src/test/compile-fail/E0045.rs b/src/test/compile-fail/E0045.rs
index edec911..2a73159 100644
--- a/src/test/compile-fail/E0045.rs
+++ b/src/test/compile-fail/E0045.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-extern "rust-call" { fn foo(x: u8, ...); } //~ ERROR E0045
+extern "Rust" { fn foo(x: u8, ...); } //~ ERROR E0045
 
 fn main() {
 }
diff --git a/src/test/compile-fail/array-not-vector.rs b/src/test/compile-fail/array-not-vector.rs
index 1bbccae..47e1c09 100644
--- a/src/test/compile-fail/array-not-vector.rs
+++ b/src/test/compile-fail/array-not-vector.rs
@@ -12,7 +12,7 @@
     let _x: i32 = [1, 2, 3];
     //~^ ERROR mismatched types
     //~| expected type `i32`
-    //~| found type `[_; 3]`
+    //~| found type `[{integer}; 3]`
     //~| expected i32, found array of 3 elements
 
     let x: &[i32] = &[1, 2, 3];
diff --git a/src/test/compile-fail/array_const_index-0.rs b/src/test/compile-fail/array_const_index-0.rs
index e652303..501c66e 100644
--- a/src/test/compile-fail/array_const_index-0.rs
+++ b/src/test/compile-fail/array_const_index-0.rs
@@ -10,7 +10,8 @@
 
 const A: &'static [i32] = &[];
 const B: i32 = (&A)[1];
-//~^ ERROR index out of bounds: the len is 0 but the index is 1
+//~^ ERROR constant evaluation error
+//~| index out of bounds: the len is 0 but the index is 1
 
 fn main() {
     let _ = B;
diff --git a/src/test/compile-fail/array_const_index-1.rs b/src/test/compile-fail/array_const_index-1.rs
index 69d84e2..d3b43e8 100644
--- a/src/test/compile-fail/array_const_index-1.rs
+++ b/src/test/compile-fail/array_const_index-1.rs
@@ -10,7 +10,8 @@
 
 const A: [i32; 0] = [];
 const B: i32 = A[1];
-//~^ ERROR index out of bounds: the len is 0 but the index is 1
+//~^ ERROR constant evaluation error
+//~| index out of bounds: the len is 0 but the index is 1
 
 fn main() {
     let _ = B;
diff --git a/src/test/compile-fail/associated-const-array-len.rs b/src/test/compile-fail/associated-const-array-len.rs
index 5d8007d..0239986 100644
--- a/src/test/compile-fail/associated-const-array-len.rs
+++ b/src/test/compile-fail/associated-const-array-len.rs
@@ -14,7 +14,7 @@
     const ID: usize;
 }
 
-const X: [i32; <i32 as Foo>::ID] = [0, 1, 2]; //~ ERROR E0250
+const X: [i32; <i32 as Foo>::ID] = [0, 1, 2]; //~ ERROR E0080
 
 fn main() {
     assert_eq!(1, X);
diff --git a/src/test/compile-fail/associated-const-impl-wrong-type.rs b/src/test/compile-fail/associated-const-impl-wrong-type.rs
index 4658d0f..95508a3 100644
--- a/src/test/compile-fail/associated-const-impl-wrong-type.rs
+++ b/src/test/compile-fail/associated-const-impl-wrong-type.rs
@@ -18,9 +18,8 @@
 
 impl Foo for SignedBar {
     const BAR: i32 = -1;
-    //~^ ERROR implemented const `BAR` has an incompatible type for trait
-    //~| expected u32,
-    //~| found i32 [E0326]
+    //~^ ERROR implemented const `BAR` has an incompatible type for trait [E0326]
+    //~| expected u32, found i32
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/associated-const-type-parameter-arrays-2.rs b/src/test/compile-fail/associated-const-type-parameter-arrays-2.rs
index 2f68735..c3fa396 100644
--- a/src/test/compile-fail/associated-const-type-parameter-arrays-2.rs
+++ b/src/test/compile-fail/associated-const-type-parameter-arrays-2.rs
@@ -25,7 +25,8 @@
 }
 
 pub fn test<A: Foo, B: Foo>() {
-    let _array = [4; <A as Foo>::Y]; //~ error: expected constant integer
+    let _array = [4; <A as Foo>::Y]; //~ ERROR E0080
+                                     //~| non-constant path in constant
 }
 
 fn main() {
diff --git a/src/test/compile-fail/associated-types-eq-3.rs b/src/test/compile-fail/associated-types-eq-3.rs
index 8c66160..cb952f6 100644
--- a/src/test/compile-fail/associated-types-eq-3.rs
+++ b/src/test/compile-fail/associated-types-eq-3.rs
@@ -47,10 +47,8 @@
     let a = 42;
     foo1(a);
     //~^ ERROR type mismatch resolving
-    //~| expected usize
-    //~| found struct `Bar`
+    //~| expected usize, found struct `Bar`
     baz(&a);
     //~^ ERROR type mismatch resolving
-    //~| expected usize
-    //~| found struct `Bar`
+    //~| expected usize, found struct `Bar`
 }
diff --git a/src/test/compile-fail/associated-types/bound-lifetime-constrained.rs b/src/test/compile-fail/associated-types/bound-lifetime-constrained.rs
index f60f06b..de6ce79 100644
--- a/src/test/compile-fail/associated-types/bound-lifetime-constrained.rs
+++ b/src/test/compile-fail/associated-types/bound-lifetime-constrained.rs
@@ -12,7 +12,6 @@
 
 #![allow(dead_code)]
 #![feature(rustc_attrs)]
-#![feature(unboxed_closures)]
 #![deny(hr_lifetime_in_assoc_type)]
 
 trait Foo<'a> {
diff --git a/src/test/compile-fail/associated-types/cache/wasm-issue-32330.rs b/src/test/compile-fail/associated-types/cache/wasm-issue-32330.rs
index 01db477..6ba09ac 100644
--- a/src/test/compile-fail/associated-types/cache/wasm-issue-32330.rs
+++ b/src/test/compile-fail/associated-types/cache/wasm-issue-32330.rs
@@ -13,7 +13,6 @@
 
 #![allow(dead_code, unused_variables)]
 #![deny(hr_lifetime_in_assoc_type)]
-#![feature(unboxed_closures)]
 
 use std::str::Chars;
 
diff --git a/src/test/compile-fail/associated-types/higher-ranked-projection.rs b/src/test/compile-fail/associated-types/higher-ranked-projection.rs
new file mode 100644
index 0000000..12341fa
--- /dev/null
+++ b/src/test/compile-fail/associated-types/higher-ranked-projection.rs
@@ -0,0 +1,38 @@
+// 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.
+
+#![feature(rustc_attrs)]
+
+// revisions: good bad
+
+trait Mirror {
+    type Image;
+}
+
+impl<T> Mirror for T {
+    type Image = T;
+}
+
+#[cfg(bad)]
+fn foo<U, T>(_t: T)
+    where for<'a> &'a T: Mirror<Image=U>
+{}
+
+#[cfg(good)]
+fn foo<U, T>(_t: T)
+    where for<'a> &'a T: Mirror<Image=&'a U>
+{}
+
+#[rustc_error]
+fn main() { //[good]~ ERROR compilation successful
+    foo(());
+    //[bad]~^ ERROR type mismatch resolving `for<'a> <&'a _ as Mirror>::Image == _`
+    //[bad]~| expected bound lifetime parameter 'a, found concrete lifetime
+}
diff --git a/src/test/compile-fail/bad-const-type.rs b/src/test/compile-fail/bad-const-type.rs
index ee6ac33..5547d19 100644
--- a/src/test/compile-fail/bad-const-type.rs
+++ b/src/test/compile-fail/bad-const-type.rs
@@ -11,6 +11,6 @@
 static i: String = 10;
 //~^ ERROR mismatched types
 //~| expected type `std::string::String`
-//~| found type `_`
+//~| found type `{integer}`
 //~| expected struct `std::string::String`, found integral variable
 fn main() { println!("{}", i); }
diff --git a/src/test/compile-fail/borrowck/borrowck-call-is-borrow-issue-12224.rs b/src/test/compile-fail/borrowck/borrowck-call-is-borrow-issue-12224.rs
index 7626f35..e4ae565 100644
--- a/src/test/compile-fail/borrowck/borrowck-call-is-borrow-issue-12224.rs
+++ b/src/test/compile-fail/borrowck/borrowck-call-is-borrow-issue-12224.rs
@@ -10,8 +10,6 @@
 
 // Ensure that invoking a closure counts as a unique immutable borrow
 
-#![feature(unboxed_closures)]
-
 type Fn<'a> = Box<FnMut() + 'a>;
 
 struct Test<'a> {
diff --git a/src/test/compile-fail/borrowck/borrowck-unboxed-closures.rs b/src/test/compile-fail/borrowck/borrowck-unboxed-closures.rs
index 1c12ca9c..0f9829a 100644
--- a/src/test/compile-fail/borrowck/borrowck-unboxed-closures.rs
+++ b/src/test/compile-fail/borrowck/borrowck-unboxed-closures.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(overloaded_calls, unboxed_closures)]
-
 fn a<F:Fn(isize, isize) -> isize>(mut f: F) {
     let g = &mut f;
     f(1, 2);    //~ ERROR cannot borrow `f` as immutable
diff --git a/src/test/compile-fail/coerce-mut.rs b/src/test/compile-fail/coerce-mut.rs
index 634d124..86702a7 100644
--- a/src/test/compile-fail/coerce-mut.rs
+++ b/src/test/compile-fail/coerce-mut.rs
@@ -15,6 +15,6 @@
     f(&x);
     //~^ ERROR mismatched types
     //~| expected type `&mut i32`
-    //~| found type `&_`
+    //~| found type `&{integer}`
     //~| values differ in mutability
 }
diff --git a/src/test/compile-fail/coercion-slice.rs b/src/test/compile-fail/coercion-slice.rs
index bd7e6c2..a619f33 100644
--- a/src/test/compile-fail/coercion-slice.rs
+++ b/src/test/compile-fail/coercion-slice.rs
@@ -14,6 +14,6 @@
     let _: &[i32] = [0];
     //~^ ERROR mismatched types
     //~| expected type `&[i32]`
-    //~| found type `[_; 1]`
+    //~| found type `[{integer}; 1]`
     //~| expected &-ptr, found array of 1 elements
 }
diff --git a/src/test/compile-fail/const-array-oob.rs b/src/test/compile-fail/const-array-oob.rs
index faabed4..b980bc0 100644
--- a/src/test/compile-fail/const-array-oob.rs
+++ b/src/test/compile-fail/const-array-oob.rs
@@ -16,7 +16,8 @@
 const BAR: u32 = FOO[5]; // no error, because the error below occurs before regular const eval
 
 const BLUB: [u32; FOO[4]] = [5, 6];
-//~^ ERROR array length constant evaluation error: index out of bounds: the len is 3 but the index is 4 [E0250]
+//~^ ERROR constant evaluation error [E0080]
+//~| index out of bounds: the len is 3 but the index is 4
 
 fn main() {
     let _ = BAR;
diff --git a/src/test/compile-fail/const-call.rs b/src/test/compile-fail/const-call.rs
index 1143d3b..7e2eabf 100644
--- a/src/test/compile-fail/const-call.rs
+++ b/src/test/compile-fail/const-call.rs
@@ -15,5 +15,6 @@
 }
 
 fn main() {
-    let _ = [0; f(2)]; //~ ERROR: non-constant path in constant expression [E0307]
+    let _ = [0; f(2)]; //~ ERROR constant evaluation error [E0080]
+                       //~| non-constant path in constant expression
 }
diff --git a/src/test/compile-fail/const-err.rs b/src/test/compile-fail/const-err.rs
index a1d3888..f207980 100644
--- a/src/test/compile-fail/const-err.rs
+++ b/src/test/compile-fail/const-err.rs
@@ -22,21 +22,29 @@
 
 // Make sure that the two uses get two errors.
 const FOO: u8 = [5u8][1];
-//~^ ERROR index out of bounds: the len is 1 but the index is 1
-//~^^ ERROR index out of bounds: the len is 1 but the index is 1
+//~^ ERROR constant evaluation error
+//~| index out of bounds: the len is 1 but the index is 1
+//~^^^ ERROR constant evaluation error
+//~| index out of bounds: the len is 1 but the index is 1
 
 fn main() {
     let a = -std::i8::MIN;
-    //~^ WARN attempted to negate with overflow
+    //~^ WARN this expression will panic at run-time
+    //~| attempted to negate with overflow
     let b = 200u8 + 200u8 + 200u8;
-    //~^ WARN attempted to add with overflow
-    //~| WARN attempted to add with overflow
+    //~^ WARN this expression will panic at run-time
+    //~| attempted to add with overflow
+    //~^^^ WARN this expression will panic at run-time
+    //~| attempted to add with overflow
     let c = 200u8 * 4;
-    //~^ WARN attempted to multiply with overflow
+    //~^ WARN this expression will panic at run-time
+    //~| attempted to multiply with overflow
     let d = 42u8 - (42u8 + 1);
-    //~^ WARN attempted to subtract with overflow
+    //~^ WARN this expression will panic at run-time
+    //~| attempted to subtract with overflow
     let _e = [5u8][1];
-    //~^ WARN index out of bounds: the len is 1 but the index is 1
+    //~^ WARN this expression will panic at run-time
+    //~| index out of bounds: the len is 1 but the index is 1
     black_box(a);
     black_box(b);
     black_box(c);
diff --git a/src/test/compile-fail/const-eval-overflow-2.rs b/src/test/compile-fail/const-eval-overflow-2.rs
index 07e27a7..4749457 100644
--- a/src/test/compile-fail/const-eval-overflow-2.rs
+++ b/src/test/compile-fail/const-eval-overflow-2.rs
@@ -19,13 +19,16 @@
 
 const NEG_128: i8 = -128;
 const NEG_NEG_128: i8 = -NEG_128;
-//~^ ERROR constant evaluation error: attempted to negate with overflow
-//~| ERROR attempted to negate with overflow
-//~| ERROR attempted to negate with overflow
+//~^ ERROR constant evaluation error
+//~| attempted to negate with overflow
+//~| ERROR constant evaluation error
+//~| attempted to negate with overflow
+//~| ERROR constant evaluation error
+//~| attempted to negate with overflow
 
 fn main() {
     match -128i8 {
-        NEG_NEG_128 => println!("A"), //~ NOTE in pattern here
+        NEG_NEG_128 => println!("A"), //~ NOTE for pattern here
         _ => println!("B"),
     }
 }
diff --git a/src/test/compile-fail/const-eval-overflow-3.rs b/src/test/compile-fail/const-eval-overflow-3.rs
index c90ae04..c78c74e 100644
--- a/src/test/compile-fail/const-eval-overflow-3.rs
+++ b/src/test/compile-fail/const-eval-overflow-3.rs
@@ -17,7 +17,7 @@
 // self-hosted and a cross-compiled setup; therefore resorting to
 // error-pattern for now.
 
-// error-pattern: expected constant integer for repeat count, but attempted to add with overflow
+// error-pattern: attempted to add with overflow
 
 #![allow(unused_imports)]
 
diff --git a/src/test/compile-fail/const-eval-overflow-4b.rs b/src/test/compile-fail/const-eval-overflow-4b.rs
index 31e1a72..9e7a5ec 100644
--- a/src/test/compile-fail/const-eval-overflow-4b.rs
+++ b/src/test/compile-fail/const-eval-overflow-4b.rs
@@ -20,9 +20,8 @@
 
 const A_I8_T
     : [u32; (i8::MAX as i8 + 1u8) as usize]
-    //~^ ERROR mismatched types:
-    //~| expected `i8`,
-    //~| found `u8` [E0250]
+    //~^ ERROR constant evaluation error [E0080]
+    //~| expected i8, found u8
     = [0; (i8::MAX as usize) + 1];
 
 
@@ -33,7 +32,8 @@
 
 const A_BAD_CHAR_USIZE
     : [u32; 5i8 as char as usize]
-    //~^ ERROR only `u8` can be cast as `char`, not `i8`
+    //~^ ERROR constant evaluation error
+    //~| only `u8` can be cast as `char`, not `i8`
     = [0; 5];
 
 fn main() {}
diff --git a/src/test/compile-fail/const-eval-overflow.rs b/src/test/compile-fail/const-eval-overflow.rs
index 3dfcb5b..c1c6935 100644
--- a/src/test/compile-fail/const-eval-overflow.rs
+++ b/src/test/compile-fail/const-eval-overflow.rs
@@ -21,86 +21,114 @@
 
 const VALS_I8: (i8, i8, i8, i8) =
     (-i8::MIN,
-     //~^ ERROR attempted to negate with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to negate with overflow
      i8::MIN - 1,
-     //~^ ERROR attempted to subtract with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to subtract with overflow
      i8::MAX + 1,
-     //~^ ERROR attempted to add with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to add with overflow
      i8::MIN * 2,
-     //~^ ERROR attempted to multiply with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to multiply with overflow
      );
 
 const VALS_I16: (i16, i16, i16, i16) =
     (-i16::MIN,
-     //~^ ERROR attempted to negate with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to negate with overflow
      i16::MIN - 1,
-     //~^ ERROR attempted to subtract with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to subtract with overflow
      i16::MAX + 1,
-     //~^ ERROR attempted to add with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to add with overflow
      i16::MIN * 2,
-     //~^ ERROR attempted to multiply with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to multiply with overflow
      );
 
 const VALS_I32: (i32, i32, i32, i32) =
     (-i32::MIN,
-     //~^ ERROR attempted to negate with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to negate with overflow
      i32::MIN - 1,
-     //~^ ERROR attempted to subtract with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to subtract with overflow
      i32::MAX + 1,
-     //~^ ERROR attempted to add with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to add with overflow
      i32::MIN * 2,
-     //~^ ERROR attempted to multiply with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to multiply with overflow
      );
 
 const VALS_I64: (i64, i64, i64, i64) =
     (-i64::MIN,
-     //~^ ERROR attempted to negate with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to negate with overflow
      i64::MIN - 1,
-     //~^ ERROR attempted to subtract with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to subtract with overflow
      i64::MAX + 1,
-     //~^ ERROR attempted to add with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to add with overflow
      i64::MAX * 2,
-     //~^ ERROR attempted to multiply with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to multiply with overflow
      );
 
 const VALS_U8: (u8, u8, u8, u8) =
     (-(u8::MIN as i8) as u8,
      u8::MIN - 1,
-     //~^ ERROR attempted to subtract with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to subtract with overflow
      u8::MAX + 1,
-     //~^ ERROR attempted to add with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to add with overflow
      u8::MAX * 2,
-     //~^ ERROR attempted to multiply with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to multiply with overflow
      );
 
 const VALS_U16: (u16, u16, u16, u16) =
     (-(u16::MIN as i16) as u16,
      u16::MIN - 1,
-     //~^ ERROR attempted to subtract with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to subtract with overflow
      u16::MAX + 1,
-     //~^ ERROR attempted to add with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to add with overflow
      u16::MAX * 2,
-     //~^ ERROR attempted to multiply with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to multiply with overflow
      );
 
 const VALS_U32: (u32, u32, u32, u32) =
     (-(u32::MIN as i32) as u32,
      u32::MIN - 1,
-     //~^ ERROR attempted to subtract with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to subtract with overflow
      u32::MAX + 1,
-     //~^ ERROR attempted to add with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to add with overflow
      u32::MAX * 2,
-     //~^ ERROR attempted to multiply with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to multiply with overflow
      );
 
 const VALS_U64: (u64, u64, u64, u64) =
     (-(u64::MIN as i64) as u64,
      u64::MIN - 1,
-     //~^ ERROR attempted to subtract with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to subtract with overflow
      u64::MAX + 1,
-     //~^ ERROR attempted to add with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to add with overflow
      u64::MAX * 2,
-     //~^ ERROR attempted to multiply with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to multiply with overflow
      );
 
 fn main() {
diff --git a/src/test/compile-fail/const-eval-span.rs b/src/test/compile-fail/const-eval-span.rs
index 9fdd24c..7335142 100644
--- a/src/test/compile-fail/const-eval-span.rs
+++ b/src/test/compile-fail/const-eval-span.rs
@@ -14,7 +14,8 @@
 struct S(i32);
 
 const CONSTANT: S = S(0);
-//~^ ERROR: unimplemented constant expression: tuple struct constructors [E0080]
+//~^ ERROR E0080
+//~| unimplemented constant expression: tuple struct constructors
 
 enum E {
     V = CONSTANT,
diff --git a/src/test/compile-fail/const-fn-error.rs b/src/test/compile-fail/const-fn-error.rs
index 45a00de..dd0f058 100644
--- a/src/test/compile-fail/const-fn-error.rs
+++ b/src/test/compile-fail/const-fn-error.rs
@@ -17,10 +17,11 @@
     for i in 0..x {
         sum += i;
     }
-    sum //~ ERROR: E0250
+    sum //~ ERROR E0080
+        //~| non-constant path in constant
 }
 
 #[allow(unused_variables)]
 fn main() {
-    let a : [i32; f(X)];
+    let a : [i32; f(X)]; //~ NOTE for array length here
 }
diff --git a/src/test/compile-fail/const-index-feature-gate.rs b/src/test/compile-fail/const-index-feature-gate.rs
index 09822e4..4f92770 100644
--- a/src/test/compile-fail/const-index-feature-gate.rs
+++ b/src/test/compile-fail/const-index-feature-gate.rs
@@ -9,7 +9,8 @@
 // except according to those terms.
 
 const ARR: [usize; 1] = [2];
-const ARR2: [i32; ARR[0]] = [5, 6]; //~ ERROR unstable
+const ARR2: [i32; ARR[0]] = [5, 6]; //~ ERROR E0080
+                                    //~| unstable
 
 fn main() {
 }
diff --git a/src/test/compile-fail/const-integer-bool-ops.rs b/src/test/compile-fail/const-integer-bool-ops.rs
index 0d6cf3b..5dadd89 100644
--- a/src/test/compile-fail/const-integer-bool-ops.rs
+++ b/src/test/compile-fail/const-integer-bool-ops.rs
@@ -8,30 +8,34 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-const X: usize = 42 && 39; //~ ERROR: can't do this op on integrals
+const X: usize = 42 && 39; //~ ERROR E0080
+                           //~| can't do this op on integrals
 const ARR: [i32; X] = [99; 34]; //~ NOTE: for array length here
 
-const X1: usize = 42 || 39; //~ ERROR: can't do this op on integrals
+const X1: usize = 42 || 39; //~ ERROR E0080
+                            //~| can't do this op on integrals
 const ARR1: [i32; X1] = [99; 47]; //~ NOTE: for array length here
 
-const X2: usize = -42 || -39; //~ ERROR: unary negation of unsigned integer
+const X2: usize = -42 || -39; //~ ERROR E0080
+                              //~| unary negation of unsigned integer
 const ARR2: [i32; X2] = [99; 18446744073709551607]; //~ NOTE: for array length here
 
-const X3: usize = -42 && -39; //~ ERROR: unary negation of unsigned integer
+const X3: usize = -42 && -39; //~ ERROR E0080
+                              //~| unary negation of unsigned integer
 const ARR3: [i32; X3] = [99; 6]; //~ NOTE: for array length here
 
 const Y: usize = 42.0 == 42.0;
-const ARRR: [i32; Y] = [99; 1]; //~ ERROR: expected usize value for array length
+const ARRR: [i32; Y] = [99; 1]; //~ ERROR: expected usize for array length
 const Y1: usize = 42.0 >= 42.0;
-const ARRR1: [i32; Y] = [99; 1]; //~ ERROR: expected usize value for array length
+const ARRR1: [i32; Y] = [99; 1]; //~ ERROR: expected usize for array length
 const Y2: usize = 42.0 <= 42.0;
-const ARRR2: [i32; Y] = [99; 1]; //~ ERROR: expected usize value for array length
+const ARRR2: [i32; Y] = [99; 1]; //~ ERROR: expected usize for array length
 const Y3: usize = 42.0 > 42.0;
-const ARRR3: [i32; Y] = [99; 0]; //~ ERROR: expected usize value for array length
+const ARRR3: [i32; Y] = [99; 0]; //~ ERROR: expected usize for array length
 const Y4: usize = 42.0 < 42.0;
-const ARRR4: [i32; Y] = [99; 0]; //~ ERROR: expected usize value for array length
+const ARRR4: [i32; Y] = [99; 0]; //~ ERROR: expected usize for array length
 const Y5: usize = 42.0 != 42.0;
-const ARRR5: [i32; Y] = [99; 0]; //~ ERROR: expected usize value for array length
+const ARRR5: [i32; Y] = [99; 0]; //~ ERROR: expected usize for array length
 
 fn main() {
     let _ = ARR;
diff --git a/src/test/compile-fail/const-len-underflow-separate-spans.rs b/src/test/compile-fail/const-len-underflow-separate-spans.rs
index 9c6b774..43375ee 100644
--- a/src/test/compile-fail/const-len-underflow-separate-spans.rs
+++ b/src/test/compile-fail/const-len-underflow-separate-spans.rs
@@ -15,7 +15,8 @@
 const ONE: usize = 1;
 const TWO: usize = 2;
 const LEN: usize = ONE - TWO;
-//~^ ERROR array length constant evaluation error: attempted to subtract with overflow [E0250]
+//~^ ERROR E0080
+//~| attempted to subtract with overflow
 
 fn main() {
     let a: [i8; LEN] = unimplemented!();
diff --git a/src/test/compile-fail/const-len-underflow-subspans.rs b/src/test/compile-fail/const-len-underflow-subspans.rs
index d51f310..e338f20 100644
--- a/src/test/compile-fail/const-len-underflow-subspans.rs
+++ b/src/test/compile-fail/const-len-underflow-subspans.rs
@@ -16,5 +16,6 @@
 
 fn main() {
     let a: [i8; ONE - TWO] = unimplemented!();
-    //~^ ERROR array length constant evaluation error: attempted to subtract with overflow [E0250]
+    //~^ ERROR constant evaluation error [E0080]
+    //~| attempted to subtract with overflow
 }
diff --git a/src/test/compile-fail/const-pattern-not-const-evaluable.rs b/src/test/compile-fail/const-pattern-not-const-evaluable.rs
index 4567cd4..d68d636 100644
--- a/src/test/compile-fail/const-pattern-not-const-evaluable.rs
+++ b/src/test/compile-fail/const-pattern-not-const-evaluable.rs
@@ -17,22 +17,26 @@
 use Cake::*;
 
 const BOO: (Cake, Cake) = (Marmor, BlackForest);
-//~^ ERROR: constant evaluation error: unimplemented constant expression: enum variants [E0471]
+//~^ ERROR: constant evaluation error [E0080]
+//~| unimplemented constant expression: enum variants
 const FOO: Cake = BOO.1;
 
 const fn foo() -> Cake {
-    Marmor //~ ERROR: constant evaluation error: unimplemented constant expression: enum variants
-    //~^ ERROR: unimplemented constant expression: enum variants
+    Marmor
+        //~^ ERROR: constant evaluation error [E0080]
+        //~| unimplemented constant expression: enum variants
+        //~^^^ ERROR: constant evaluation error [E0080]
+        //~| unimplemented constant expression: enum variants
 }
 
 const WORKS: Cake = Marmor;
 
-const GOO: Cake = foo();
+const GOO: Cake = foo(); //~ NOTE for expression here
 
 fn main() {
     match BlackForest {
-        FOO => println!("hi"), //~ NOTE: in pattern here
-        GOO => println!("meh"), //~ NOTE: in pattern here
+        FOO => println!("hi"), //~ NOTE: for pattern here
+        GOO => println!("meh"), //~ NOTE: for pattern here
         WORKS => println!("möp"),
         _ => println!("bye"),
     }
diff --git a/src/test/compile-fail/const-slice-oob.rs b/src/test/compile-fail/const-slice-oob.rs
index d63b009..b1b4bfe 100644
--- a/src/test/compile-fail/const-slice-oob.rs
+++ b/src/test/compile-fail/const-slice-oob.rs
@@ -10,7 +10,8 @@
 
 const FOO: &'static[u32] = &[1, 2, 3];
 const BAR: u32 = FOO[5];
-//~^ ERROR index out of bounds: the len is 3 but the index is 5
+//~^ ERROR constant evaluation error [E0080]
+//~| index out of bounds: the len is 3 but the index is 5
 
 fn main() {
     let _ = BAR;
diff --git a/src/test/compile-fail/const-tup-index-span.rs b/src/test/compile-fail/const-tup-index-span.rs
index 9d3c432..6f095b3 100644
--- a/src/test/compile-fail/const-tup-index-span.rs
+++ b/src/test/compile-fail/const-tup-index-span.rs
@@ -11,7 +11,8 @@
 // Test spans of errors
 
 const TUP: (usize,) = 5 << 64;
-//~^ ERROR: attempted to shift left with overflow [E0250]
+//~^ ERROR E0080
+//~| attempted to shift left with overflow
 const ARR: [i32; TUP.0] = [];
 
 fn main() {
diff --git a/src/test/compile-fail/discrim-ill-typed.rs b/src/test/compile-fail/discrim-ill-typed.rs
index 23106c9..c73b7e8 100644
--- a/src/test/compile-fail/discrim-ill-typed.rs
+++ b/src/test/compile-fail/discrim-ill-typed.rs
@@ -25,7 +25,8 @@
         Ok = i8::MAX - 1,
         Ok2,
         OhNo = 0_u8,
-        //~^ ERROR mismatched types
+        //~^ ERROR E0080
+        //~| expected i8, found u8
     }
 
     let x = A::Ok;
@@ -37,7 +38,8 @@
         Ok = u8::MAX - 1,
         Ok2,
         OhNo = 0_i8,
-        //~^  ERROR mismatched types
+        //~^ ERROR E0080
+        //~| expected u8, found i8
     }
 
     let x = A::Ok;
@@ -49,7 +51,8 @@
         Ok = i16::MAX - 1,
         Ok2,
         OhNo = 0_u16,
-        //~^ ERROR mismatched types
+        //~^ ERROR E0080
+        //~| expected i16, found u16
     }
 
     let x = A::Ok;
@@ -61,7 +64,8 @@
         Ok = u16::MAX - 1,
         Ok2,
         OhNo = 0_i16,
-        //~^ ERROR mismatched types
+        //~^ ERROR E0080
+        //~| expected u16, found i16
     }
 
     let x = A::Ok;
@@ -73,7 +77,8 @@
         Ok = i32::MAX - 1,
         Ok2,
         OhNo = 0_u32,
-        //~^ ERROR mismatched types
+        //~^ ERROR E0080
+        //~| expected i32, found u32
     }
 
     let x = A::Ok;
@@ -85,7 +90,8 @@
         Ok = u32::MAX - 1,
         Ok2,
         OhNo = 0_i32,
-        //~^ ERROR mismatched types
+        //~^ ERROR E0080
+        //~| expected u32, found i32
     }
 
     let x = A::Ok;
@@ -97,7 +103,8 @@
         Ok = i64::MAX - 1,
         Ok2,
         OhNo = 0_u64,
-        //~^ ERROR mismatched types
+        //~^ ERROR E0080
+        //~| expected i64, found u64
     }
 
     let x = A::Ok;
@@ -109,7 +116,8 @@
         Ok = u64::MAX - 1,
         Ok2,
         OhNo = 0_i64,
-        //~^ ERROR mismatched types
+        //~^ ERROR E0080
+        //~| expected u64, found i64
     }
 
     let x = A::Ok;
diff --git a/src/test/compile-fail/enable-orbit-for-incr-comp.rs b/src/test/compile-fail/enable-orbit-for-incr-comp.rs
new file mode 100644
index 0000000..eec6bad
--- /dev/null
+++ b/src/test/compile-fail/enable-orbit-for-incr-comp.rs
@@ -0,0 +1,20 @@
+// 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.
+
+// ignore-pretty
+// compile-flags:-Zincremental=tmp/cfail-tests/enable-orbit-for-incr-comp -Zorbit=off
+// error-pattern:Automatically enabling `-Z orbit` because `-Z incremental` was specified
+
+#![deny(warnings)]
+
+fn main() {
+    FAIL! // We just need some compilation error. What we really care about is
+          // that the error pattern above is checked.
+}
diff --git a/src/test/compile-fail/enum-discrim-too-small.rs b/src/test/compile-fail/enum-discrim-too-small.rs
index d6ba09b..bbdb389 100644
--- a/src/test/compile-fail/enum-discrim-too-small.rs
+++ b/src/test/compile-fail/enum-discrim-too-small.rs
@@ -13,28 +13,32 @@
 enum Eu8 {
     Au8 = 23,
     Bu8 = 223,
-    Cu8 = -23, //~ ERROR unary negation of unsigned integer
+    Cu8 = -23, //~ ERROR E0080
+               //~| unary negation of unsigned integer
 }
 
 #[repr(u16)]
 enum Eu16 {
     Au16 = 23,
     Bu16 = 55555,
-    Cu16 = -22333, //~ ERROR unary negation of unsigned integer
+    Cu16 = -22333, //~ ERROR E0080
+                   //~| unary negation of unsigned integer
 }
 
 #[repr(u32)]
 enum Eu32 {
     Au32 = 23,
     Bu32 = 3_000_000_000,
-    Cu32 = -2_000_000_000, //~ ERROR unary negation of unsigned integer
+    Cu32 = -2_000_000_000, //~ ERROR E0080
+                           //~| unary negation of unsigned integer
 }
 
 #[repr(u64)]
 enum Eu64 {
     Au32 = 23,
     Bu32 = 3_000_000_000,
-    Cu32 = -2_000_000_000, //~ ERROR unary negation of unsigned integer
+    Cu32 = -2_000_000_000, //~ ERROR E0080
+                           //~| unary negation of unsigned integer
 }
 
 // u64 currently allows negative numbers, and i64 allows numbers greater than `1<<63`.  This is a
diff --git a/src/test/compile-fail/eval-enum.rs b/src/test/compile-fail/eval-enum.rs
index 7ca274b..57db583 100644
--- a/src/test/compile-fail/eval-enum.rs
+++ b/src/test/compile-fail/eval-enum.rs
@@ -9,9 +9,11 @@
 // except according to those terms.
 
 enum test {
-    div_zero = 1/0, //~ERROR constant evaluation error: attempted to divide by zero
+    div_zero = 1/0, //~ ERROR E0080
+                    //~| attempted to divide by zero
     rem_zero = 1%0,
-//~^ ERROR constant evaluation error: attempted to calculate the remainder with a divisor of zero
+    //~^ ERROR E0080
+    //~| attempted to calculate the remainder with a divisor of zero
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/explicit-self-lifetime-mismatch.rs b/src/test/compile-fail/explicit-self-lifetime-mismatch.rs
index b5432fa..f8aa1ea 100644
--- a/src/test/compile-fail/explicit-self-lifetime-mismatch.rs
+++ b/src/test/compile-fail/explicit-self-lifetime-mismatch.rs
@@ -14,15 +14,17 @@
 }
 
 impl<'a,'b> Foo<'a,'b> {
-    fn bar(self: Foo<'b,'a>) {}
-    //~^ ERROR mismatched types
+    fn bar(
+        self
+    //~^ ERROR mismatched method receiver
     //~| expected type `Foo<'a, 'b>`
     //~| found type `Foo<'b, 'a>`
     //~| lifetime mismatch
-    //~| ERROR mismatched types
+    //~| ERROR mismatched method receiver
     //~| expected type `Foo<'a, 'b>`
     //~| found type `Foo<'b, 'a>`
     //~| lifetime mismatch
+            : Foo<'b,'a>) {}
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/feature-gate-abi.rs b/src/test/compile-fail/feature-gate-abi.rs
new file mode 100644
index 0000000..0c01f95
--- /dev/null
+++ b/src/test/compile-fail/feature-gate-abi.rs
@@ -0,0 +1,60 @@
+// 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.
+
+// Functions
+extern "rust-intrinsic" fn f1() {} //~ ERROR intrinsics are subject to change
+extern "platform-intrinsic" fn f2() {} //~ ERROR platform intrinsics are experimental
+extern "vectorcall" fn f3() {} //~ ERROR vectorcall is experimental and subject to change
+extern "rust-call" fn f4() {} //~ ERROR rust-call ABI is subject to change
+
+// Methods in trait definition
+trait Tr {
+    extern "rust-intrinsic" fn m1(); //~ ERROR intrinsics are subject to change
+    extern "platform-intrinsic" fn m2(); //~ ERROR platform intrinsics are experimental
+    extern "vectorcall" fn m3(); //~ ERROR vectorcall is experimental and subject to change
+    extern "rust-call" fn m4(); //~ ERROR rust-call ABI is subject to change
+
+    extern "rust-intrinsic" fn dm1() {} //~ ERROR intrinsics are subject to change
+    extern "platform-intrinsic" fn dm2() {} //~ ERROR platform intrinsics are experimental
+    extern "vectorcall" fn dm3() {} //~ ERROR vectorcall is experimental and subject to change
+    extern "rust-call" fn dm4() {} //~ ERROR rust-call ABI is subject to change
+}
+
+struct S;
+
+// Methods in trait impl
+impl Tr for S {
+    extern "rust-intrinsic" fn m1() {} //~ ERROR intrinsics are subject to change
+    extern "platform-intrinsic" fn m2() {} //~ ERROR platform intrinsics are experimental
+    extern "vectorcall" fn m3() {} //~ ERROR vectorcall is experimental and subject to change
+    extern "rust-call" fn m4() {} //~ ERROR rust-call ABI is subject to change
+}
+
+// Methods in inherent impl
+impl S {
+    extern "rust-intrinsic" fn im1() {} //~ ERROR intrinsics are subject to change
+    extern "platform-intrinsic" fn im2() {} //~ ERROR platform intrinsics are experimental
+    extern "vectorcall" fn im3() {} //~ ERROR vectorcall is experimental and subject to change
+    extern "rust-call" fn im4() {} //~ ERROR rust-call ABI is subject to change
+}
+
+// Function pointer types
+type A1 = extern "rust-intrinsic" fn(); //~ ERROR intrinsics are subject to change
+type A2 = extern "platform-intrinsic" fn(); //~ ERROR platform intrinsics are experimental
+type A3 = extern "vectorcall" fn(); //~ ERROR vectorcall is experimental and subject to change
+type A4 = extern "rust-call" fn(); //~ ERROR rust-call ABI is subject to change
+
+// Foreign modules
+extern "rust-intrinsic" {} //~ ERROR intrinsics are subject to change
+extern "platform-intrinsic" {} //~ ERROR platform intrinsics are experimental
+extern "vectorcall" {} //~ ERROR vectorcall is experimental and subject to change
+extern "rust-call" {} //~ ERROR rust-call ABI is subject to change
+
+fn main() {}
diff --git a/src/test/compile-fail/feature-gate-negate-unsigned0.rs b/src/test/compile-fail/feature-gate-negate-unsigned0.rs
index 05b1943..89ae1a0 100644
--- a/src/test/compile-fail/feature-gate-negate-unsigned0.rs
+++ b/src/test/compile-fail/feature-gate-negate-unsigned0.rs
@@ -18,14 +18,17 @@
 
 fn main() {
     let a = -1;
-    //~^ ERROR unary negation of unsigned integer
+    //~^ ERROR E0080
+    //~| unary negation of unsigned integer
     let _b : u8 = a; // for infering variable a to u8.
 
     let _d = -1u8;
-    //~^ ERROR unary negation of unsigned integer
+    //~^ ERROR E0080
+    //~| unary negation of unsigned integer
 
     for _ in -10..10u8 {}
-    //~^ ERROR unary negation of unsigned integer
+    //~^ ERROR E0080
+    //~| unary negation of unsigned integer
 
     -S; // should not trigger the gate; issue 26840
 }
diff --git a/src/test/compile-fail/feature-gate-unboxed-closures-method-calls.rs b/src/test/compile-fail/feature-gate-unboxed-closures-method-calls.rs
index eea1f61..253d163 100644
--- a/src/test/compile-fail/feature-gate-unboxed-closures-method-calls.rs
+++ b/src/test/compile-fail/feature-gate-unboxed-closures-method-calls.rs
@@ -11,9 +11,9 @@
 #![allow(dead_code)]
 
 fn foo<F: Fn()>(mut f: F) {
-    f.call(()); //~ ERROR explicit use of unboxed closure method `call`
-    f.call_mut(()); //~ ERROR explicit use of unboxed closure method `call_mut`
-    f.call_once(()); //~ ERROR explicit use of unboxed closure method `call_once`
+    f.call(()); //~ ERROR use of unstable library feature 'fn_traits'
+    f.call_mut(()); //~ ERROR use of unstable library feature 'fn_traits'
+    f.call_once(()); //~ ERROR use of unstable library feature 'fn_traits'
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/feature-gate-unboxed-closures-ufcs-calls.rs b/src/test/compile-fail/feature-gate-unboxed-closures-ufcs-calls.rs
index f15c5c4..902b3c1 100644
--- a/src/test/compile-fail/feature-gate-unboxed-closures-ufcs-calls.rs
+++ b/src/test/compile-fail/feature-gate-unboxed-closures-ufcs-calls.rs
@@ -10,10 +10,10 @@
 
 #![allow(dead_code)]
 
-fn foo<F: Fn()>(mut f: F, mut g: F) {
-    Fn::call(&g, ()); //~ ERROR explicit use of unboxed closure method `call`
-    FnMut::call_mut(&mut g, ()); //~ ERROR explicit use of unboxed closure method `call_mut`
-    FnOnce::call_once(g, ()); //~ ERROR explicit use of unboxed closure method `call_once`
+fn foo<F: Fn()>(mut f: F) {
+    Fn::call(&f, ()); //~ ERROR use of unstable library feature 'fn_traits'
+    FnMut::call_mut(&mut f, ()); //~ ERROR use of unstable library feature 'fn_traits'
+    FnOnce::call_once(f, ()); //~ ERROR use of unstable library feature 'fn_traits'
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/fn-trait-formatting.rs b/src/test/compile-fail/fn-trait-formatting.rs
index fd140cd..e01a041 100644
--- a/src/test/compile-fail/fn-trait-formatting.rs
+++ b/src/test/compile-fail/fn-trait-formatting.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(unboxed_closures)]
 #![feature(box_syntax)]
 
 fn needs_fn<F>(x: F) where F: Fn(isize) -> isize {}
diff --git a/src/test/compile-fail/fully-qualified-type-name1.rs b/src/test/compile-fail/fully-qualified-type-name1.rs
index 5ea8ce2..1a7ceb2 100644
--- a/src/test/compile-fail/fully-qualified-type-name1.rs
+++ b/src/test/compile-fail/fully-qualified-type-name1.rs
@@ -15,6 +15,6 @@
     x = 5;
     //~^ ERROR mismatched types
     //~| expected type `std::option::Option<usize>`
-    //~| found type `_`
+    //~| found type `{integer}`
     //~| expected enum `std::option::Option`, found integral variable
 }
diff --git a/src/test/compile-fail/if-let-arm-types.rs b/src/test/compile-fail/if-let-arm-types.rs
index c7b1e1a..40013a7 100644
--- a/src/test/compile-fail/if-let-arm-types.rs
+++ b/src/test/compile-fail/if-let-arm-types.rs
@@ -12,7 +12,7 @@
     if let Some(b) = None { //~ ERROR: `if let` arms have incompatible types
         //~^ expected (), found integral variable
         //~| expected type `()`
-        //~| found type `_`
+        //~| found type `{integer}`
         ()
     } else {                //~ NOTE: `if let` arm with an incompatible type
         1
diff --git a/src/test/compile-fail/ifmt-bad-arg.rs b/src/test/compile-fail/ifmt-bad-arg.rs
index 272ad98..59c61a4 100644
--- a/src/test/compile-fail/ifmt-bad-arg.rs
+++ b/src/test/compile-fail/ifmt-bad-arg.rs
@@ -41,6 +41,12 @@
     //~^ ERROR invalid reference to argument `0` (no arguments given)
     //~^^ ERROR invalid reference to argument `1` (no arguments given)
 
+    // bad named arguments, #35082
+
+    format!("{valuea} {valueb}", valuea=5, valuec=7);
+    //~^ ERROR there is no argument named `valueb`
+    //~^^ ERROR named argument never used
+
     // bad syntax of the format string
 
     format!("{"); //~ ERROR: expected `'}'` but string was terminated
diff --git a/src/test/compile-fail/indexing-requires-a-uint.rs b/src/test/compile-fail/indexing-requires-a-uint.rs
index 354d7b9..61d54b3 100644
--- a/src/test/compile-fail/indexing-requires-a-uint.rs
+++ b/src/test/compile-fail/indexing-requires-a-uint.rs
@@ -13,7 +13,7 @@
 
 fn main() {
     fn bar<T>(_: T) {}
-    [0][0u8]; //~ ERROR: `[_]: std::ops::Index<u8>` is not satisfied
+    [0][0u8]; //~ ERROR: `[{integer}]: std::ops::Index<u8>` is not satisfied
 
     [0][0]; // should infer to be a usize
 
diff --git a/src/test/compile-fail/integral-variable-unification-error.rs b/src/test/compile-fail/integral-variable-unification-error.rs
index 99f2d25..f2686ae 100644
--- a/src/test/compile-fail/integral-variable-unification-error.rs
+++ b/src/test/compile-fail/integral-variable-unification-error.rs
@@ -12,7 +12,7 @@
     let mut x = 2;
     x = 5.0;
     //~^ ERROR mismatched types
-    //~| expected type `_`
-    //~| found type `_`
+    //~| expected type `{integer}`
+    //~| found type `{float}`
     //~| expected integral variable, found floating-point variable
 }
diff --git a/src/test/compile-fail/invalid-path-in-const.rs b/src/test/compile-fail/invalid-path-in-const.rs
index 3c4ad5a..9a9358b 100644
--- a/src/test/compile-fail/invalid-path-in-const.rs
+++ b/src/test/compile-fail/invalid-path-in-const.rs
@@ -10,5 +10,6 @@
 
 fn main() {
     fn f(a: [u8; u32::DOESNOTEXIST]) {}
-    //~^ ERROR unresolved path in constant expression
+    //~^ ERROR constant evaluation error
+    //~| unresolved path in constant expression
 }
diff --git a/src/test/compile-fail/issue-13033.rs b/src/test/compile-fail/issue-13033.rs
index 43cf70e..3d9d814 100644
--- a/src/test/compile-fail/issue-13033.rs
+++ b/src/test/compile-fail/issue-13033.rs
@@ -16,7 +16,9 @@
 
 impl Foo for Baz {
     fn bar(&mut self, other: &Foo) {}
-    //~^ ERROR method `bar` has an incompatible type for trait: values differ in mutability [E0053]
+    //~^ ERROR method `bar` has an incompatible type for trait
+    //~| expected type `fn(&mut Baz, &mut Foo)`
+    //~| found type `fn(&mut Baz, &Foo)`
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/issue-13466.rs b/src/test/compile-fail/issue-13466.rs
index 17b9641..abddf6b 100644
--- a/src/test/compile-fail/issue-13466.rs
+++ b/src/test/compile-fail/issue-13466.rs
@@ -17,13 +17,13 @@
     let _x: usize = match Some(1) {
         Ok(u) => u,
         //~^ ERROR mismatched types
-        //~| expected type `std::option::Option<_>`
+        //~| expected type `std::option::Option<{integer}>`
         //~| found type `std::result::Result<_, _>`
         //~| expected enum `std::option::Option`, found enum `std::result::Result`
 
         Err(e) => panic!(e)
         //~^ ERROR mismatched types
-        //~| expected type `std::option::Option<_>`
+        //~| expected type `std::option::Option<{integer}>`
         //~| found type `std::result::Result<_, _>`
         //~| expected enum `std::option::Option`, found enum `std::result::Result`
     };
diff --git a/src/test/compile-fail/issue-15094.rs b/src/test/compile-fail/issue-15094.rs
index 42e3456..da48bbb 100644
--- a/src/test/compile-fail/issue-15094.rs
+++ b/src/test/compile-fail/issue-15094.rs
@@ -20,8 +20,8 @@
     type Output = ();
     fn call_once(self, _args: ()) {
     //~^ ERROR `call_once` has an incompatible type for trait
-    //~| expected "rust-call" fn,
-    //~| found "Rust" fn
+    //~| expected type `extern "rust-call" fn
+    //~| found type `fn
         println!("{:?}", self.x);
     }
 }
diff --git a/src/test/compile-fail/issue-16939.rs b/src/test/compile-fail/issue-16939.rs
index 7ec3fef..e16c58b 100644
--- a/src/test/compile-fail/issue-16939.rs
+++ b/src/test/compile-fail/issue-16939.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(overloaded_calls, unboxed_closures)]
-
 // Make sure we don't ICE when making an overloaded call with the
 // wrong arity.
 
diff --git a/src/test/compile-fail/issue-17033.rs b/src/test/compile-fail/issue-17033.rs
index f0fe01b..0ec05b9 100644
--- a/src/test/compile-fail/issue-17033.rs
+++ b/src/test/compile-fail/issue-17033.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(overloaded_calls)]
-
 fn f<'r>(p: &'r mut fn(p: &mut ())) {
     (*p)(()) //~  ERROR mismatched types
              //~| expected type `&mut ()`
diff --git a/src/test/compile-fail/issue-17545.rs b/src/test/compile-fail/issue-17545.rs
index 8480021..49435f8 100644
--- a/src/test/compile-fail/issue-17545.rs
+++ b/src/test/compile-fail/issue-17545.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(unboxed_closures)]
-
 pub fn foo<'a, F: Fn(&'a ())>(bar: F) {
     bar.call((
         &(), //~ ERROR borrowed value does not live long enough
diff --git a/src/test/compile-fail/issue-17551.rs b/src/test/compile-fail/issue-17551.rs
index 5781cb7..5e69553d 100644
--- a/src/test/compile-fail/issue-17551.rs
+++ b/src/test/compile-fail/issue-17551.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(unboxed_closures)]
-
 use std::marker;
 
 struct B<T>(marker::PhantomData<T>);
diff --git a/src/test/compile-fail/issue-17651.rs b/src/test/compile-fail/issue-17651.rs
index 0fe01ec..3ea136a 100644
--- a/src/test/compile-fail/issue-17651.rs
+++ b/src/test/compile-fail/issue-17651.rs
@@ -14,5 +14,5 @@
 fn main() {
     // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
     (|| Box::new(*(&[0][..])))();
-    //~^ ERROR `[_]: std::marker::Sized` is not satisfied
+    //~^ ERROR `[{integer}]: std::marker::Sized` is not satisfied
 }
diff --git a/src/test/compile-fail/issue-17740.rs b/src/test/compile-fail/issue-17740.rs
index 6b9294b..664d62e 100644
--- a/src/test/compile-fail/issue-17740.rs
+++ b/src/test/compile-fail/issue-17740.rs
@@ -14,11 +14,11 @@
 
 impl <'a> Foo<'a>{
     fn bar(self: &mut Foo) {
-    //~^ mismatched types
+    //~^ mismatched method receiver
     //~| expected type `&mut Foo<'a>`
     //~| found type `&mut Foo<'_>`
     //~| lifetime mismatch
-    //~| mismatched types
+    //~| mismatched method receiver
     //~| expected type `&mut Foo<'a>`
     //~| found type `&mut Foo<'_>`
     //~| lifetime mismatch
diff --git a/src/test/compile-fail/issue-18532.rs b/src/test/compile-fail/issue-18532.rs
index 9cf922a..94eab97c 100644
--- a/src/test/compile-fail/issue-18532.rs
+++ b/src/test/compile-fail/issue-18532.rs
@@ -12,8 +12,6 @@
 // when a type error or unconstrained type variable propagates
 // into it.
 
-#![feature(unboxed_closures)]
-
 fn main() {
     (return)((),());
     //~^ ERROR the type of this value must be known
diff --git a/src/test/compile-fail/issue-19521.rs b/src/test/compile-fail/issue-19521.rs
index 58a95e9..93d95ca 100644
--- a/src/test/compile-fail/issue-19521.rs
+++ b/src/test/compile-fail/issue-19521.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(unboxed_closures)]
-
 fn main() {
     "".homura()(); //~ ERROR no method named `homura` found
 }
diff --git a/src/test/compile-fail/issue-19707.rs b/src/test/compile-fail/issue-19707.rs
index 9affb44..beeb7da 100644
--- a/src/test/compile-fail/issue-19707.rs
+++ b/src/test/compile-fail/issue-19707.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(unboxed_closures)]
 #![allow(dead_code)]
 
 type foo = fn(&u8, &u8) -> &u8; //~ ERROR missing lifetime specifier
diff --git a/src/test/compile-fail/issue-19991.rs b/src/test/compile-fail/issue-19991.rs
index b368daa..e07dfaf 100644
--- a/src/test/compile-fail/issue-19991.rs
+++ b/src/test/compile-fail/issue-19991.rs
@@ -14,7 +14,7 @@
 fn main() {
     if let Some(homura) = Some("madoka") { //~  ERROR missing an else clause
                                            //~| expected type `()`
-                                           //~| found type `_`
+                                           //~| found type `{integer}`
                                            //~| expected (), found integral variable
         765
     };
diff --git a/src/test/compile-fail/issue-21332.rs b/src/test/compile-fail/issue-21332.rs
index b369181..db33348 100644
--- a/src/test/compile-fail/issue-21332.rs
+++ b/src/test/compile-fail/issue-21332.rs
@@ -14,8 +14,7 @@
     type Item = i32;
     fn next(&mut self) -> Result<i32, i32> { Ok(7) }
     //~^ ERROR method `next` has an incompatible type for trait
-    //~| expected enum `std::option::Option`
-    //~|    found enum `std::result::Result` [E0053]
+    //~| expected enum `std::option::Option`, found enum `std::result::Result`
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/issue-22933-2.rs b/src/test/compile-fail/issue-22933-2.rs
index 7d619c2..54a2408 100644
--- a/src/test/compile-fail/issue-22933-2.rs
+++ b/src/test/compile-fail/issue-22933-2.rs
@@ -12,10 +12,12 @@
     Pie      = 0x1,
     Apple    = 0x2,
     ApplePie = Delicious::Apple as isize | Delicious::PIE as isize,
-    //~^ ERROR constant evaluation error: unresolved path in constant expression
+    //~^ ERROR constant evaluation error
+    //~| unresolved path in constant expression
 }
 
 const FOO: [u32; u8::MIN as usize] = [];
-//~^ ERROR array length constant evaluation error: unresolved path in constant expression
+//~^ ERROR constant evaluation error
+//~| unresolved path in constant expression
 
 fn main() {}
diff --git a/src/test/compile-fail/issue-23217.rs b/src/test/compile-fail/issue-23217.rs
index 32cdd6b..c2bcbb9 100644
--- a/src/test/compile-fail/issue-23217.rs
+++ b/src/test/compile-fail/issue-23217.rs
@@ -10,7 +10,8 @@
 
 pub enum SomeEnum {
     B = SomeEnum::A,
-    //~^ ERROR constant evaluation error: unresolved path in constant expression
+    //~^ ERROR constant evaluation error
+    //~| unresolved path in constant expression
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/issue-24356.rs b/src/test/compile-fail/issue-24356.rs
index 27d46be..ede81be 100644
--- a/src/test/compile-fail/issue-24356.rs
+++ b/src/test/compile-fail/issue-24356.rs
@@ -30,9 +30,6 @@
         impl Deref for Thing {
             //~^ ERROR not all trait items implemented, missing: `Target` [E0046]
             fn deref(&self) -> i8 { self.0 }
-            //~^ ERROR method `deref` has an incompatible type for trait
-            //~| expected &-ptr
-            //~| found i8 [E0053]
         }
 
         let thing = Thing(72);
diff --git a/src/test/compile-fail/issue-25145.rs b/src/test/compile-fail/issue-25145.rs
index e8a9c8d..93f75e9 100644
--- a/src/test/compile-fail/issue-25145.rs
+++ b/src/test/compile-fail/issue-25145.rs
@@ -17,6 +17,7 @@
 }
 
 static STUFF: [u8; S::N] = [0; S::N];
-//~^ ERROR array length constant evaluation error: unresolved path in constant expression
+//~^ ERROR constant evaluation error
+//~| unresolved path in constant expression
 
 fn main() {}
diff --git a/src/test/compile-fail/issue-26237.rs b/src/test/compile-fail/issue-26237.rs
index 11e236d..22772e5 100644
--- a/src/test/compile-fail/issue-26237.rs
+++ b/src/test/compile-fail/issue-26237.rs
@@ -11,7 +11,7 @@
 macro_rules! macro_panic {
     ($not_a_function:expr, $some_argument:ident) => {
         $not_a_function($some_argument)
-        //~^ ERROR expected function, found `_`
+        //~^ ERROR expected function, found `{integer}`
     }
 }
 
diff --git a/src/test/compile-fail/issue-27008.rs b/src/test/compile-fail/issue-27008.rs
index bdcbaf0..ee6ec52 100644
--- a/src/test/compile-fail/issue-27008.rs
+++ b/src/test/compile-fail/issue-27008.rs
@@ -16,5 +16,5 @@
     //~| expected type `usize`
     //~| found type `S`
     //~| expected usize, found struct `S`
-    //~| ERROR expected positive integer for repeat count, found struct
+    //~| ERROR expected usize for repeat count, found struct
 }
diff --git a/src/test/compile-fail/issue-27895.rs b/src/test/compile-fail/issue-27895.rs
index 3b3abc9..ca8d5a1 100644
--- a/src/test/compile-fail/issue-27895.rs
+++ b/src/test/compile-fail/issue-27895.rs
@@ -14,7 +14,8 @@
 
     match i {
         0...index => println!("winner"),
-        //~^ ERROR non-constant path in constant expression
+        //~^ ERROR constant evaluation error
+        //~| non-constant path in constant expression
         _ => println!("hello"),
     }
 }
diff --git a/src/test/compile-fail/issue-28586.rs b/src/test/compile-fail/issue-28586.rs
index c8a1e424d..1dfd146 100644
--- a/src/test/compile-fail/issue-28586.rs
+++ b/src/test/compile-fail/issue-28586.rs
@@ -11,6 +11,6 @@
 // Regression test for issue #28586
 
 pub trait Foo {}
-impl Foo for [u8; usize::BYTES] {} //~ ERROR E0250
+impl Foo for [u8; usize::BYTES] {} //~ ERROR E0080
 
 fn main() { }
diff --git a/src/test/compile-fail/issue-31173.rs b/src/test/compile-fail/issue-31173.rs
new file mode 100644
index 0000000..fb1e3cc
--- /dev/null
+++ b/src/test/compile-fail/issue-31173.rs
@@ -0,0 +1,27 @@
+// 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.
+
+use std::vec::IntoIter;
+
+pub fn get_tok(it: &mut IntoIter<u8>) {
+    let mut found_e = false;
+
+    let temp: Vec<u8> = it.take_while(|&x| {
+        found_e = true;
+        false
+    })
+        .cloned()
+        //~^ ERROR type mismatch resolving
+        //~| expected type `u8`
+        //~| found type `&_`
+        .collect(); //~ ERROR no method named `collect`
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-34349.rs b/src/test/compile-fail/issue-34349.rs
new file mode 100644
index 0000000..5917531
--- /dev/null
+++ b/src/test/compile-fail/issue-34349.rs
@@ -0,0 +1,32 @@
+// 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.
+
+// This is a regression test for a problem encountered around upvar
+// inference and trait caching: in particular, we were entering a
+// temporary closure kind during inference, and then caching results
+// based on that temporary kind, which led to no error being reported
+// in this particular test.
+
+fn main() {
+    let inc = || {};
+    inc();
+
+    fn apply<F>(f: F) where F: Fn() {
+        f()
+    }
+
+    let mut farewell = "goodbye".to_owned();
+    let diary = || { //~ ERROR E0525
+        farewell.push_str("!!!");
+        println!("Then I screamed {}.", farewell);
+    };
+
+    apply(diary);
+}
diff --git a/src/test/compile-fail/feature-gate-abi-vectorcall.rs b/src/test/compile-fail/issue-35075.rs
similarity index 69%
rename from src/test/compile-fail/feature-gate-abi-vectorcall.rs
rename to src/test/compile-fail/issue-35075.rs
index 79f3c8d..a70452d 100644
--- a/src/test/compile-fail/feature-gate-abi-vectorcall.rs
+++ b/src/test/compile-fail/issue-35075.rs
@@ -8,12 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-extern "vectorcall" {   //~ ERROR vectorcall is experimental and subject to change
-    fn bar();
+struct Bar<T> {
+    inner: Foo<T> //~ ERROR type name `Foo` is undefined or not in scope
 }
 
-extern "vectorcall" fn baz() {  //~ ERROR vectorcall is experimental and subject to change
+enum Baz<T> {
+    Foo(Foo<T>) //~ ERROR type name `Foo` is undefined or not in scope
 }
 
-fn main() {
-}
+fn main() {}
diff --git a/src/test/compile-fail/issue-35139.rs b/src/test/compile-fail/issue-35139.rs
new file mode 100644
index 0000000..67f0e7a
--- /dev/null
+++ b/src/test/compile-fail/issue-35139.rs
@@ -0,0 +1,36 @@
+// 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.
+
+use std::fmt;
+
+pub trait MethodType {
+    type GetProp: ?Sized;
+}
+
+pub struct MTFn;
+
+impl<'a> MethodType for MTFn { //~ ERROR E0207
+    type GetProp = fmt::Debug + 'a;
+}
+
+fn bad(a: Box<<MTFn as MethodType>::GetProp>) -> Box<fmt::Debug+'static> {
+    a
+}
+
+fn dangling(a: &str) -> Box<fmt::Debug> {
+    bad(Box::new(a))
+}
+
+fn main() {
+    let mut s = "hello".to_string();
+    let x = dangling(&s);
+    s = String::new();
+    println!("{:?}", x);
+}
diff --git a/src/test/compile-fail/issue-3521.rs b/src/test/compile-fail/issue-3521.rs
index 52375ef..1b6e4b1 100644
--- a/src/test/compile-fail/issue-3521.rs
+++ b/src/test/compile-fail/issue-3521.rs
@@ -15,7 +15,8 @@
     enum Stuff {
         Bar = foo
         //~^ ERROR attempt to use a non-constant value in a constant
-        //~^^ ERROR constant evaluation error: non-constant path in constant expression
+        //~^^ ERROR constant evaluation error
+        //~| non-constant path in constant expression
     }
 
     println!("{}", Stuff::Bar);
diff --git a/src/test/compile-fail/issue-3907.rs b/src/test/compile-fail/issue-3907.rs
index c99ff18..cbc09a0 100644
--- a/src/test/compile-fail/issue-3907.rs
+++ b/src/test/compile-fail/issue-3907.rs
@@ -11,14 +11,14 @@
 // aux-build:issue_3907.rs
 extern crate issue_3907;
 
-type Foo = issue_3907::Foo; //~ NOTE: type aliases cannot be used for traits
+type Foo = issue_3907::Foo;
 
 struct S {
     name: isize
 }
 
 impl Foo for S { //~ ERROR: `Foo` is not a trait
-    //~| `Foo` is not a trait
+                 //~| NOTE: type aliases cannot be used for traits
     fn bar() { }
 }
 
diff --git a/src/test/compile-fail/issue-4201.rs b/src/test/compile-fail/issue-4201.rs
index 5842334..b1f668d 100644
--- a/src/test/compile-fail/issue-4201.rs
+++ b/src/test/compile-fail/issue-4201.rs
@@ -14,7 +14,7 @@
     } else if false {
 //~^ ERROR if may be missing an else clause
 //~| expected type `()`
-//~| found type `_`
+//~| found type `{integer}`
 //~| expected (), found integral variable
         1
     };
diff --git a/src/test/compile-fail/issue-4335.rs b/src/test/compile-fail/issue-4335.rs
index 0089bff..9a1b5d9 100644
--- a/src/test/compile-fail/issue-4335.rs
+++ b/src/test/compile-fail/issue-4335.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(unboxed_closures)]
-
 fn id<T>(t: T) -> T { t }
 
 fn f<'r, T>(v: &'r T) -> Box<FnMut() -> T + 'r> {
diff --git a/src/test/compile-fail/issue-4968.rs b/src/test/compile-fail/issue-4968.rs
index 7c09058..77588e5 100644
--- a/src/test/compile-fail/issue-4968.rs
+++ b/src/test/compile-fail/issue-4968.rs
@@ -14,7 +14,7 @@
 fn main() {
     match 42 { A => () }
     //~^ ERROR mismatched types
-    //~| expected type `_`
+    //~| expected type `{integer}`
     //~| found type `(isize, isize)`
     //~| expected integral variable, found tuple
 }
diff --git a/src/test/compile-fail/issue-5035.rs b/src/test/compile-fail/issue-5035.rs
index a186a39..9648d64 100644
--- a/src/test/compile-fail/issue-5035.rs
+++ b/src/test/compile-fail/issue-5035.rs
@@ -10,7 +10,10 @@
 
 trait I {}
 type K = I;
-//~^ NOTE: aliases cannot be used for traits
 impl K for isize {} //~ ERROR: `K` is not a trait
-//~| is not a trait
+                    //~| NOTE: aliases cannot be used for traits
+
+use ImportError; //~ ERROR unresolved
+impl ImportError for () {} // check that this is not an additional error (c.f. #35142)
+
 fn main() {}
diff --git a/src/test/compile-fail/issue-7867.rs b/src/test/compile-fail/issue-7867.rs
index e0de860..ed46511 100644
--- a/src/test/compile-fail/issue-7867.rs
+++ b/src/test/compile-fail/issue-7867.rs
@@ -25,12 +25,12 @@
     match &Some(42) {
         Some(x) => (),
         //~^ ERROR mismatched types
-        //~| expected type `&std::option::Option<_>`
+        //~| expected type `&std::option::Option<{integer}>`
         //~| found type `std::option::Option<_>`
         //~| expected &-ptr, found enum `std::option::Option`
         None => ()
         //~^ ERROR mismatched types
-        //~| expected type `&std::option::Option<_>`
+        //~| expected type `&std::option::Option<{integer}>`
         //~| found type `std::option::Option<_>`
         //~| expected &-ptr, found enum `std::option::Option`
     }
diff --git a/src/test/compile-fail/issue-8761.rs b/src/test/compile-fail/issue-8761.rs
index 1c98abc..91a07dd 100644
--- a/src/test/compile-fail/issue-8761.rs
+++ b/src/test/compile-fail/issue-8761.rs
@@ -10,13 +10,11 @@
 
 enum Foo {
     A = 1i64,
-    //~^ ERROR mismatched types:
-    //~| expected `isize`,
-    //~| found `i64` [E0080]
+    //~^ ERROR constant evaluation error
+    //~| expected isize, found i64
     B = 2u8
-    //~^ ERROR mismatched types:
-    //~| expected `isize`,
-    //~| found `u8` [E0080]
+    //~^ ERROR constant evaluation error
+    //~| expected isize, found u8
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/kindck-impl-type-params-2.rs b/src/test/compile-fail/kindck-impl-type-params-2.rs
index 1cf970e..a455a7b 100644
--- a/src/test/compile-fail/kindck-impl-type-params-2.rs
+++ b/src/test/compile-fail/kindck-impl-type-params-2.rs
@@ -21,5 +21,5 @@
 fn main() {
     let x: Box<_> = box 3;
     take_param(&x);
-    //~^ ERROR `Box<_>: std::marker::Copy` is not satisfied
+    //~^ ERROR `Box<{integer}>: std::marker::Copy` is not satisfied
 }
diff --git a/src/test/compile-fail/lint-forbid-attr.rs b/src/test/compile-fail/lint-forbid-attr.rs
index fcc8fb6..fd2513c 100644
--- a/src/test/compile-fail/lint-forbid-attr.rs
+++ b/src/test/compile-fail/lint-forbid-attr.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![forbid(deprecated)]
+//~^ NOTE `forbid` lint level set here
 
 #[allow(deprecated)] //~ ERROR allow(deprecated) overruled by outer forbid(deprecated)
 fn main() {
diff --git a/src/test/compile-fail/feature-gate-abi-vectorcall.rs b/src/test/compile-fail/macro-tt-matchers.rs
similarity index 69%
copy from src/test/compile-fail/feature-gate-abi-vectorcall.rs
copy to src/test/compile-fail/macro-tt-matchers.rs
index 79f3c8d..f41da77 100644
--- a/src/test/compile-fail/feature-gate-abi-vectorcall.rs
+++ b/src/test/compile-fail/macro-tt-matchers.rs
@@ -8,12 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-extern "vectorcall" {   //~ ERROR vectorcall is experimental and subject to change
-    fn bar();
+#![feature(rustc_attrs)]
+
+macro_rules! foo {
+    ($x:tt) => (type Alias = $x<i32>;)
 }
 
-extern "vectorcall" fn baz() {  //~ ERROR vectorcall is experimental and subject to change
-}
+foo!(Box);
 
-fn main() {
-}
+#[rustc_error]
+fn main() {} //~ ERROR compilation successful
diff --git a/src/test/compile-fail/match-range-fail.rs b/src/test/compile-fail/match-range-fail.rs
index 526aa83..f89b3e39 100644
--- a/src/test/compile-fail/match-range-fail.rs
+++ b/src/test/compile-fail/match-range-fail.rs
@@ -20,13 +20,14 @@
         10 ... "what" => ()
     };
     //~^^ ERROR only char and numeric types are allowed in range
-    //~| start type: _
+    //~| start type: {integer}
     //~| end type: &'static str
 
     match 5 {
         'c' ... 100 => { }
         _ => { }
     };
-    //~^^^ ERROR mismatched types in range
-    //~| expected char, found integral variable
+    //~^^^ ERROR mismatched types
+    //~| expected type `{integer}`
+    //~| found type `char`
 }
diff --git a/src/test/compile-fail/match-vec-mismatch.rs b/src/test/compile-fail/match-vec-mismatch.rs
index 3ac4958..596cec1 100644
--- a/src/test/compile-fail/match-vec-mismatch.rs
+++ b/src/test/compile-fail/match-vec-mismatch.rs
@@ -18,7 +18,7 @@
     };
 
     match &[0, 1, 2] {
-        [..] => {} //~ ERROR expected an array or slice, found `&[_; 3]`
+        [..] => {} //~ ERROR expected an array or slice, found `&[{integer}; 3]`
     };
 
     match &[0, 1, 2] {
diff --git a/src/test/compile-fail/method-self-arg-1.rs b/src/test/compile-fail/method-self-arg-1.rs
index ffa5287..0381636 100644
--- a/src/test/compile-fail/method-self-arg-1.rs
+++ b/src/test/compile-fail/method-self-arg-1.rs
@@ -24,6 +24,6 @@
                  //~| expected &-ptr, found struct `Foo`
     Foo::bar(&42); //~  ERROR mismatched types
                       //~| expected type `&Foo`
-                      //~| found type `&_`
+                      //~| found type `&{integer}`
                       //~| expected struct `Foo`, found integral variable
 }
diff --git a/src/test/compile-fail/moves-based-on-type-no-recursive-stack-closure.rs b/src/test/compile-fail/moves-based-on-type-no-recursive-stack-closure.rs
index 5af326b..df9a351 100644
--- a/src/test/compile-fail/moves-based-on-type-no-recursive-stack-closure.rs
+++ b/src/test/compile-fail/moves-based-on-type-no-recursive-stack-closure.rs
@@ -12,8 +12,6 @@
 // bound must be noncopyable. For details see
 // http://smallcultfollowing.com/babysteps/blog/2013/04/30/the-case-of-the-recurring-closure/
 
-#![feature(unboxed_closures)]
-
 struct R<'a> {
     // This struct is needed to create the
     // otherwise infinite type of a fn that
diff --git a/src/test/compile-fail/mut-pattern-mismatched.rs b/src/test/compile-fail/mut-pattern-mismatched.rs
index 63e7dbd..318d121 100644
--- a/src/test/compile-fail/mut-pattern-mismatched.rs
+++ b/src/test/compile-fail/mut-pattern-mismatched.rs
@@ -14,7 +14,7 @@
     // (separate lines to ensure the spans are accurate)
 
      let &_ //~  ERROR mismatched types
-            //~| expected type `&mut _`
+            //~| expected type `&mut {integer}`
             //~| found type `&_`
             //~| values differ in mutability
         = foo;
@@ -23,7 +23,7 @@
     let bar = &1;
     let &_ = bar;
     let &mut _ //~  ERROR mismatched types
-               //~| expected type `&_`
+               //~| expected type `&{integer}`
                //~| found type `&mut _`
                //~| values differ in mutability
          = bar;
diff --git a/src/test/compile-fail/no-patterns-in-args.rs b/src/test/compile-fail/no-patterns-in-args.rs
new file mode 100644
index 0000000..3edbdf4
--- /dev/null
+++ b/src/test/compile-fail/no-patterns-in-args.rs
@@ -0,0 +1,30 @@
+// 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.
+
+extern {
+    fn f1(mut arg: u8); //~ ERROR patterns aren't allowed in foreign function declarations
+                        //~^ NOTE this is a recent error
+    fn f2(&arg: u8); //~ ERROR patterns aren't allowed in foreign function declarations
+    fn f3(arg @ _: u8); //~ ERROR patterns aren't allowed in foreign function declarations
+                        //~^ NOTE this is a recent error
+    fn g1(arg: u8); // OK
+    fn g2(_: u8); // OK
+    // fn g3(u8); // Not yet
+}
+
+type A1 = fn(mut arg: u8); //~ ERROR patterns aren't allowed in function pointer types
+                           //~^ NOTE this is a recent error
+type A2 = fn(&arg: u8); //~ ERROR patterns aren't allowed in function pointer types
+                        //~^ NOTE this is a recent error
+type B1 = fn(arg: u8); // OK
+type B2 = fn(_: u8); // OK
+type B3 = fn(u8); // OK
+
+fn main() {}
diff --git a/src/test/compile-fail/no_send-rc.rs b/src/test/compile-fail/no_send-rc.rs
index 69f6fcd..f31d378 100644
--- a/src/test/compile-fail/no_send-rc.rs
+++ b/src/test/compile-fail/no_send-rc.rs
@@ -15,5 +15,5 @@
 fn main() {
     let x = Rc::new(5);
     bar(x);
-    //~^ ERROR `std::rc::Rc<_>: std::marker::Send` is not satisfied
+    //~^ ERROR `std::rc::Rc<{integer}>: std::marker::Send` is not satisfied
 }
diff --git a/src/test/compile-fail/non-constant-enum-for-vec-repeat.rs b/src/test/compile-fail/non-constant-enum-for-vec-repeat.rs
index 9564a08..cadfec5 100644
--- a/src/test/compile-fail/non-constant-enum-for-vec-repeat.rs
+++ b/src/test/compile-fail/non-constant-enum-for-vec-repeat.rs
@@ -15,5 +15,6 @@
 
 fn main() {
     [State::ST_NULL; (State::ST_WHITESPACE as usize)];
-    //~^ ERROR expected constant integer for repeat count, but unimplemented constant expression
+    //~^ ERROR constant evaluation error
+    //~| unimplemented constant expression: enum variants
 }
diff --git a/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs b/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs
index 3ce206f..a6f88a5 100644
--- a/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs
+++ b/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs
@@ -13,6 +13,8 @@
 fn main() {
     fn bar(n: usize) {
         let _x = [0; n];
-        //~^ ERROR expected constant integer for repeat count, found variable
+        //~^ ERROR constant evaluation error
+        //~| non-constant path in constant expression
+        //~| NOTE `n` is a variable
     }
 }
diff --git a/src/test/compile-fail/non-constant-in-const-path.rs b/src/test/compile-fail/non-constant-in-const-path.rs
index ee88168..737f803 100644
--- a/src/test/compile-fail/non-constant-in-const-path.rs
+++ b/src/test/compile-fail/non-constant-in-const-path.rs
@@ -12,6 +12,7 @@
     let x = 0;
     match 1 {
         0 ... x => {}
-        //~^ ERROR non-constant path in constant expression
+        //~^ ERROR constant evaluation error
+        //~| non-constant path in constant expression
     };
 }
diff --git a/src/test/compile-fail/privacy-ns2.rs b/src/test/compile-fail/privacy-ns2.rs
index bf29622..7accf0c 100644
--- a/src/test/compile-fail/privacy-ns2.rs
+++ b/src/test/compile-fail/privacy-ns2.rs
@@ -25,15 +25,15 @@
 }
 
 fn test_single1() {
-    use foo1::Bar;  //~ ERROR function `Bar` is private
+    use foo1::Bar;
 
-    Bar();
+    Bar(); //~ ERROR unresolved name `Bar`
 }
 
 fn test_list1() {
-    use foo1::{Bar,Baz};  //~ ERROR `Bar` is private
+    use foo1::{Bar,Baz};
 
-    Bar();
+    Bar(); //~ ERROR unresolved name `Bar`
 }
 
 // private type, public value
@@ -46,15 +46,15 @@
 }
 
 fn test_single2() {
-    use foo2::Bar;  //~ ERROR trait `Bar` is private
+    use foo2::Bar;
 
-    let _x : Box<Bar>;
+    let _x : Box<Bar>; //~ ERROR type name `Bar` is undefined
 }
 
 fn test_list2() {
-    use foo2::{Bar,Baz};  //~ ERROR `Bar` is private
+    use foo2::{Bar,Baz};
 
-    let _x: Box<Bar>;
+    let _x: Box<Bar>; //~ ERROR type name `Bar` is undefined
 }
 
 // neither public
diff --git a/src/test/compile-fail/range-1.rs b/src/test/compile-fail/range-1.rs
index c00be91..dc68331 100644
--- a/src/test/compile-fail/range-1.rs
+++ b/src/test/compile-fail/range-1.rs
@@ -23,5 +23,5 @@
     // Unsized type.
     let arr: &[_] = &[1, 2, 3];
     let range = *arr..;
-    //~^ ERROR `[_]: std::marker::Sized` is not satisfied
+    //~^ ERROR `[{integer}]: std::marker::Sized` is not satisfied
 }
diff --git a/src/test/compile-fail/regionck-unboxed-closure-lifetimes.rs b/src/test/compile-fail/regionck-unboxed-closure-lifetimes.rs
index 5db9a01..8ec6036 100644
--- a/src/test/compile-fail/regionck-unboxed-closure-lifetimes.rs
+++ b/src/test/compile-fail/regionck-unboxed-closure-lifetimes.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(unboxed_closures, overloaded_calls)]
-
 use std::ops::FnMut;
 
 fn main() {
diff --git a/src/test/compile-fail/regions-escape-unboxed-closure.rs b/src/test/compile-fail/regions-escape-unboxed-closure.rs
index abbefd2..cf41fad 100644
--- a/src/test/compile-fail/regions-escape-unboxed-closure.rs
+++ b/src/test/compile-fail/regions-escape-unboxed-closure.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(unboxed_closures)]
-
 fn with_int(f: &mut FnMut(&isize)) {
 }
 
diff --git a/src/test/compile-fail/regions-return-ref-to-upvar-issue-17403.rs b/src/test/compile-fail/regions-return-ref-to-upvar-issue-17403.rs
index 1e2224e..99e5cc0 100644
--- a/src/test/compile-fail/regions-return-ref-to-upvar-issue-17403.rs
+++ b/src/test/compile-fail/regions-return-ref-to-upvar-issue-17403.rs
@@ -10,8 +10,6 @@
 
 // Test that closures cannot subvert aliasing restrictions
 
-#![feature(overloaded_calls, unboxed_closures)]
-
 fn main() {
     // Unboxed closure case
     {
diff --git a/src/test/compile-fail/regions-steal-closure.rs b/src/test/compile-fail/regions-steal-closure.rs
index a30d847..8ade8b2 100644
--- a/src/test/compile-fail/regions-steal-closure.rs
+++ b/src/test/compile-fail/regions-steal-closure.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(unboxed_closures)]
-
 struct closure_box<'a> {
     cl: Box<FnMut() + 'a>,
 }
diff --git a/src/test/compile-fail/repeat_count.rs b/src/test/compile-fail/repeat_count.rs
index ab5af64..1758b28 100644
--- a/src/test/compile-fail/repeat_count.rs
+++ b/src/test/compile-fail/repeat_count.rs
@@ -13,39 +13,38 @@
 fn main() {
     let n = 1;
     let a = [0; n];
-    //~^ ERROR expected constant integer for repeat count, found variable [E0307]
+    //~^ ERROR constant evaluation error
+    //~| non-constant path in constant expression
     let b = [0; ()];
     //~^ ERROR mismatched types
     //~| expected type `usize`
     //~| found type `()`
     //~| expected usize, found ()
-    //~| ERROR expected positive integer for repeat count, found tuple [E0306]
+    //~| ERROR expected usize for repeat count, found tuple [E0306]
     let c = [0; true];
     //~^ ERROR mismatched types
     //~| expected usize, found bool
-    //~| ERROR expected positive integer for repeat count, found boolean [E0306]
+    //~| ERROR expected usize for repeat count, found boolean [E0306]
     let d = [0; 0.5];
     //~^ ERROR mismatched types
     //~| expected type `usize`
-    //~| found type `_`
+    //~| found type `{float}`
     //~| expected usize, found floating-point variable
-    //~| ERROR expected positive integer for repeat count, found float [E0306]
+    //~| ERROR expected usize for repeat count, found float [E0306]
     let e = [0; "foo"];
     //~^ ERROR mismatched types
     //~| expected type `usize`
     //~| found type `&'static str`
     //~| expected usize, found &-ptr
-    //~| ERROR expected positive integer for repeat count, found string literal [E0306]
+    //~| ERROR expected usize for repeat count, found string literal [E0306]
     let f = [0; -4_isize];
-    //~^ ERROR mismatched types
-    //~| expected `usize`
-    //~| found `isize`
-    //~| ERROR mismatched types:
+    //~^ ERROR constant evaluation error
+    //~| expected usize, found isize
+    //~| ERROR mismatched types
     //~| expected usize, found isize
     let f = [0_usize; -1_isize];
-    //~^ ERROR mismatched types
-    //~| expected `usize`
-    //~| found `isize`
+    //~^ ERROR constant evaluation error
+    //~| expected usize, found isize
     //~| ERROR mismatched types
     //~| expected usize, found isize
     struct G {
@@ -56,5 +55,5 @@
     //~| expected type `usize`
     //~| found type `main::G`
     //~| expected usize, found struct `main::G`
-    //~| ERROR expected positive integer for repeat count, found struct [E0306]
+    //~| ERROR expected usize for repeat count, found struct [E0306]
 }
diff --git a/src/test/compile-fail/resolve-type-param-in-item-in-trait.rs b/src/test/compile-fail/resolve-type-param-in-item-in-trait.rs
index 30ff1ed..a1572b8 100644
--- a/src/test/compile-fail/resolve-type-param-in-item-in-trait.rs
+++ b/src/test/compile-fail/resolve-type-param-in-item-in-trait.rs
@@ -13,9 +13,8 @@
 // scope (in this case, the enum).
 
 trait TraitA<A> {
-    fn outer(self) {
+    fn outer(&self) {
         enum Foo<B> {
-            //~^ ERROR parameter `B` is never used
             Variance(A)
                 //~^ ERROR can't use type parameters from outer function
         }
@@ -23,23 +22,21 @@
 }
 
 trait TraitB<A> {
-    fn outer(self) {
+    fn outer(&self) {
         struct Foo<B>(A);
                 //~^ ERROR can't use type parameters from outer function
-                //~^^ ERROR parameter `B` is never used
     }
 }
 
 trait TraitC<A> {
-    fn outer(self) {
+    fn outer(&self) {
         struct Foo<B> { a: A }
                 //~^ ERROR can't use type parameters from outer function
-                //~^^ ERROR parameter `B` is never used
     }
 }
 
 trait TraitD<A> {
-    fn outer(self) {
+    fn outer(&self) {
         fn foo<B>(a: A) { }
                 //~^ ERROR can't use type parameters from outer function
     }
diff --git a/src/test/compile-fail/slightly-nice-generic-literal-messages.rs b/src/test/compile-fail/slightly-nice-generic-literal-messages.rs
index 3140bb6..2eba7c2 100644
--- a/src/test/compile-fail/slightly-nice-generic-literal-messages.rs
+++ b/src/test/compile-fail/slightly-nice-generic-literal-messages.rs
@@ -16,8 +16,8 @@
     match Foo(1.1, marker::PhantomData) {
         1 => {}
     //~^ ERROR mismatched types
-    //~| expected type `Foo<_, _>`
-    //~| found type `_`
+    //~| expected type `Foo<{float}, _>`
+    //~| found type `{integer}`
     //~| expected struct `Foo`, found integral variable
     }
 
diff --git a/src/test/compile-fail/str-idx.rs b/src/test/compile-fail/str-idx.rs
index b972a09..2b2c23a 100644
--- a/src/test/compile-fail/str-idx.rs
+++ b/src/test/compile-fail/str-idx.rs
@@ -10,5 +10,5 @@
 
 pub fn main() {
     let s: &str = "hello";
-    let c: u8 = s[4]; //~ ERROR `str: std::ops::Index<_>` is not satisfied
+    let c: u8 = s[4]; //~ ERROR `str: std::ops::Index<{integer}>` is not satisfied
 }
diff --git a/src/test/compile-fail/struct-base-wrong-type-2.rs b/src/test/compile-fail/struct-base-wrong-type-2.rs
index 1250d0d..7e5510ed 100644
--- a/src/test/compile-fail/struct-base-wrong-type-2.rs
+++ b/src/test/compile-fail/struct-base-wrong-type-2.rs
@@ -24,6 +24,6 @@
                                //~| expected struct `Foo`, found struct `Bar`
     let f__isize = Foo { a: 2, ..4 }; //~  ERROR mismatched types
                                  //~| expected type `Foo`
-                                 //~| found type `_`
+                                 //~| found type `{integer}`
                                  //~| expected struct `Foo`, found integral variable
 }
diff --git a/src/test/compile-fail/struct-base-wrong-type.rs b/src/test/compile-fail/struct-base-wrong-type.rs
index 4503e46..3703b15 100644
--- a/src/test/compile-fail/struct-base-wrong-type.rs
+++ b/src/test/compile-fail/struct-base-wrong-type.rs
@@ -23,7 +23,7 @@
                                        //~| expected struct `Foo`, found struct `Bar`
 static foo_i: Foo = Foo { a: 2, ..4 }; //~  ERROR mismatched types
                                        //~| expected type `Foo`
-                                       //~| found type `_`
+                                       //~| found type `{integer}`
                                        //~| expected struct `Foo`, found integral variable
 
 fn main() {
diff --git a/src/test/compile-fail/trait-impl-method-mismatch.rs b/src/test/compile-fail/trait-impl-method-mismatch.rs
index f86d9b7..a05e007 100644
--- a/src/test/compile-fail/trait-impl-method-mismatch.rs
+++ b/src/test/compile-fail/trait-impl-method-mismatch.rs
@@ -17,8 +17,8 @@
     // Cannot have a larger effect than the trait:
     unsafe fn jumbo(&self, x: &usize) { *self + *x; }
     //~^ ERROR method `jumbo` has an incompatible type for trait
-    //~| expected normal fn,
-    //~| found unsafe fn
+    //~| expected type `fn
+    //~| found type `unsafe fn
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/traits-inductive-overflow-simultaneous.rs b/src/test/compile-fail/traits-inductive-overflow-simultaneous.rs
index 2968e8a..777746a 100644
--- a/src/test/compile-fail/traits-inductive-overflow-simultaneous.rs
+++ b/src/test/compile-fail/traits-inductive-overflow-simultaneous.rs
@@ -26,5 +26,5 @@
 
 fn main() {
     is_ee(4);
-    //~^ ERROR overflow evaluating the requirement `_: Tweedle
+    //~^ ERROR overflow evaluating the requirement `{integer}: Tweedle
 }
diff --git a/src/test/compile-fail/tuple-arity-mismatch.rs b/src/test/compile-fail/tuple-arity-mismatch.rs
index e62255a..a71f441 100644
--- a/src/test/compile-fail/tuple-arity-mismatch.rs
+++ b/src/test/compile-fail/tuple-arity-mismatch.rs
@@ -16,7 +16,7 @@
     let y = first ((1,2.0,3));
     //~^ ERROR mismatched types
     //~| expected type `(isize, f64)`
-    //~| found type `(isize, f64, _)`
+    //~| found type `(isize, f64, {integer})`
     //~| expected a tuple with 2 elements, found one with 3 elements
 
     let y = first ((1,));
diff --git a/src/test/compile-fail/tuple-index-out-of-bounds.rs b/src/test/compile-fail/tuple-index-out-of-bounds.rs
index c2c41fb..4597cf3 100644
--- a/src/test/compile-fail/tuple-index-out-of-bounds.rs
+++ b/src/test/compile-fail/tuple-index-out-of-bounds.rs
@@ -20,5 +20,5 @@
     tuple.0;
     tuple.1;
     tuple.2;
-    //~^ ERROR attempted out-of-bounds tuple index `2` on type `(_, _)`
+    //~^ ERROR attempted out-of-bounds tuple index `2` on type `({integer}, {integer})`
 }
diff --git a/src/test/compile-fail/type-mismatch-multiple.rs b/src/test/compile-fail/type-mismatch-multiple.rs
index 0f174d9..9359c03 100644
--- a/src/test/compile-fail/type-mismatch-multiple.rs
+++ b/src/test/compile-fail/type-mismatch-multiple.rs
@@ -13,7 +13,7 @@
 fn main() { let a: bool = 1; let b: i32 = true; }
 //~^ ERROR mismatched types
 //~| expected type `bool`
-//~| found type `_`
+//~| found type `{integer}`
 //~| expected bool, found integral variable
 //~| ERROR mismatched types
 //~| expected i32, found bool
diff --git a/src/test/compile-fail/typeck-unsafe-always-share.rs b/src/test/compile-fail/typeck-unsafe-always-share.rs
index 6047f67..f017277 100644
--- a/src/test/compile-fail/typeck-unsafe-always-share.rs
+++ b/src/test/compile-fail/typeck-unsafe-always-share.rs
@@ -27,7 +27,7 @@
 fn main() {
     let us = UnsafeCell::new(MySync{u: UnsafeCell::new(0)});
     test(us);
-    //~^ ERROR `std::cell::UnsafeCell<MySync<_>>: std::marker::Sync` is not satisfied
+    //~^ ERROR `std::cell::UnsafeCell<MySync<{integer}>>: std::marker::Sync` is not satisfied
 
     let uns = UnsafeCell::new(NoSync);
     test(uns);
diff --git a/src/test/compile-fail/ufcs-explicit-self-bad.rs b/src/test/compile-fail/ufcs-explicit-self-bad.rs
index f14a350..a98b7cd 100644
--- a/src/test/compile-fail/ufcs-explicit-self-bad.rs
+++ b/src/test/compile-fail/ufcs-explicit-self-bad.rs
@@ -41,14 +41,14 @@
 
 impl<'a, T> SomeTrait for &'a Bar<T> {
     fn dummy1(self: &&'a Bar<T>) { }
-    fn dummy2(self: &Bar<T>) {} //~ ERROR mismatched types
-    //~^ ERROR mismatched types
+    fn dummy2(self: &Bar<T>) {} //~ ERROR mismatched method receiver
+    //~^ ERROR mismatched method receiver
     fn dummy3(self: &&Bar<T>) {}
-    //~^ ERROR mismatched types
+    //~^ ERROR mismatched method receiver
     //~| expected type `&&'a Bar<T>`
     //~| found type `&&Bar<T>`
     //~| lifetime mismatch
-    //~| ERROR mismatched types
+    //~| ERROR mismatched method receiver
     //~| expected type `&&'a Bar<T>`
     //~| found type `&&Bar<T>`
     //~| lifetime mismatch
diff --git a/src/test/compile-fail/unboxed-closure-immutable-capture.rs b/src/test/compile-fail/unboxed-closure-immutable-capture.rs
index 5be2738b..2d99837 100644
--- a/src/test/compile-fail/unboxed-closure-immutable-capture.rs
+++ b/src/test/compile-fail/unboxed-closure-immutable-capture.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(unboxed_closures)]
-
 // Test that even unboxed closures that are capable of mutating their
 // environment cannot mutate captured variables that have not been
 // declared mutable (#18335)
diff --git a/src/test/compile-fail/unboxed-closure-region.rs b/src/test/compile-fail/unboxed-closure-region.rs
index eee1b6c..1c86dda 100644
--- a/src/test/compile-fail/unboxed-closure-region.rs
+++ b/src/test/compile-fail/unboxed-closure-region.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(unboxed_closures)]
-
 // Test that an unboxed closure that captures a free variable by
 // reference cannot escape the region of that variable.
 fn main() {
diff --git a/src/test/compile-fail/unboxed-closure-sugar-nonexistent-trait.rs b/src/test/compile-fail/unboxed-closure-sugar-nonexistent-trait.rs
index 2145085..465bddd 100644
--- a/src/test/compile-fail/unboxed-closure-sugar-nonexistent-trait.rs
+++ b/src/test/compile-fail/unboxed-closure-sugar-nonexistent-trait.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(unboxed_closures)]
-
 fn f<F:Nonexist(isize) -> isize>(x: F) {} //~ ERROR trait `Nonexist` is not in scope
 
 type Typedef = isize;
diff --git a/src/test/compile-fail/unboxed-closures-borrow-conflict.rs b/src/test/compile-fail/unboxed-closures-borrow-conflict.rs
index 372f327..ad7e678 100644
--- a/src/test/compile-fail/unboxed-closures-borrow-conflict.rs
+++ b/src/test/compile-fail/unboxed-closures-borrow-conflict.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(unboxed_closures)]
-
 // Test that an unboxed closure that mutates a free variable will
 // cause borrow conflicts.
 
diff --git a/src/test/compile-fail/unboxed-closures-infer-argument-types-two-region-pointers.rs b/src/test/compile-fail/unboxed-closures-infer-argument-types-two-region-pointers.rs
index 1e2b018..5436a85 100644
--- a/src/test/compile-fail/unboxed-closures-infer-argument-types-two-region-pointers.rs
+++ b/src/test/compile-fail/unboxed-closures-infer-argument-types-two-region-pointers.rs
@@ -11,8 +11,6 @@
 // That a closure whose expected argument types include two distinct
 // bound regions.
 
-#![feature(unboxed_closures)]
-
 use std::cell::Cell;
 
 fn doit<T,F>(val: T, f: &F)
diff --git a/src/test/compile-fail/unboxed-closures-infer-explicit-call-too-early.rs b/src/test/compile-fail/unboxed-closures-infer-explicit-call-too-early.rs
index 226b516..62f6ee5 100644
--- a/src/test/compile-fail/unboxed-closures-infer-explicit-call-too-early.rs
+++ b/src/test/compile-fail/unboxed-closures-infer-explicit-call-too-early.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(unboxed_closures)]
-
 fn main() {
     let mut zero = || {};
     let () = zero.call_mut(());
diff --git a/src/test/compile-fail/unboxed-closures-type-mismatch.rs b/src/test/compile-fail/unboxed-closures-type-mismatch.rs
index 9118239..dba4c8c 100644
--- a/src/test/compile-fail/unboxed-closures-type-mismatch.rs
+++ b/src/test/compile-fail/unboxed-closures-type-mismatch.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(unboxed_closures)]
-
 use std::ops::FnMut;
 
 pub fn main() {
diff --git a/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs b/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs
index cba7ad8..2b0a8ba 100644
--- a/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs
+++ b/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs
@@ -10,8 +10,6 @@
 
 // Tests that unsafe extern fn pointers do not implement any Fn traits.
 
-#![feature(unboxed_closures)]
-
 use std::ops::{Fn,FnMut,FnOnce};
 
 unsafe fn square(x: &isize) -> isize { (*x) * (*x) }
diff --git a/src/test/compile-fail/unboxed-closures-wrong-abi.rs b/src/test/compile-fail/unboxed-closures-wrong-abi.rs
index dd891bc..f6ba25f 100644
--- a/src/test/compile-fail/unboxed-closures-wrong-abi.rs
+++ b/src/test/compile-fail/unboxed-closures-wrong-abi.rs
@@ -10,8 +10,6 @@
 
 // Tests that unsafe extern fn pointers do not implement any Fn traits.
 
-#![feature(unboxed_closures)]
-
 use std::ops::{Fn,FnMut,FnOnce};
 
 extern "C" fn square(x: &isize) -> isize { (*x) * (*x) }
diff --git a/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs b/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs
index f9edd5d..9d907ff 100644
--- a/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs
+++ b/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs
@@ -10,8 +10,6 @@
 
 // Tests that unsafe extern fn pointers do not implement any Fn traits.
 
-#![feature(unboxed_closures)]
-
 use std::ops::{Fn,FnMut,FnOnce};
 
 unsafe fn square(x: isize) -> isize { x * x }
diff --git a/src/test/compile-fail/unresolved-import-recovery.rs b/src/test/compile-fail/unresolved-import-recovery.rs
new file mode 100644
index 0000000..8173f69
--- /dev/null
+++ b/src/test/compile-fail/unresolved-import-recovery.rs
@@ -0,0 +1,27 @@
+// 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.
+
+// Check that unresolved imports do not create additional errors and ICEs
+
+mod m {
+    pub use unresolved; //~ ERROR unresolved import `unresolved`
+
+    fn f() {
+        let unresolved = 0; // OK
+    }
+}
+
+fn main() {
+    match 0u8 {
+        m::unresolved => {} // OK
+        m::unresolved(..) => {} // OK
+        m::unresolved{..} => {} // OK
+    }
+}
diff --git a/src/test/compile-fail/unsafe-trait-impl.rs b/src/test/compile-fail/unsafe-trait-impl.rs
index 51f8766..fb4652a 100644
--- a/src/test/compile-fail/unsafe-trait-impl.rs
+++ b/src/test/compile-fail/unsafe-trait-impl.rs
@@ -17,8 +17,8 @@
 impl Foo for u32 {
     fn len(&self) -> u32 { *self }
     //~^ ERROR method `len` has an incompatible type for trait
-    //~| expected unsafe fn,
-    //~| found normal fn
+    //~| expected type `unsafe fn(&u32) -> u32`
+    //~| found type `fn(&u32) -> u32`
 }
 
 fn main() { }
diff --git a/src/test/compile-fail/vtable-res-trait-param.rs b/src/test/compile-fail/vtable-res-trait-param.rs
index eb0baff..8b3e936 100644
--- a/src/test/compile-fail/vtable-res-trait-param.rs
+++ b/src/test/compile-fail/vtable-res-trait-param.rs
@@ -24,7 +24,7 @@
 
 fn call_it<B:TraitB>(b: B)  -> isize {
     let y = 4;
-    b.gimme_an_a(y) //~ ERROR `_: TraitA` is not satisfied
+    b.gimme_an_a(y) //~ ERROR `{integer}: TraitA` is not satisfied
 }
 
 fn main() {
diff --git a/src/test/debuginfo/var-captured-in-sendable-closure.rs b/src/test/debuginfo/var-captured-in-sendable-closure.rs
index aa269ed..b415546 100644
--- a/src/test/debuginfo/var-captured-in-sendable-closure.rs
+++ b/src/test/debuginfo/var-captured-in-sendable-closure.rs
@@ -40,7 +40,7 @@
 // lldb-check:[...]$2 = 5
 
 #![allow(unused_variables)]
-#![feature(unboxed_closures, box_syntax)]
+#![feature(box_syntax)]
 #![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
diff --git a/src/test/debuginfo/var-captured-in-stack-closure.rs b/src/test/debuginfo/var-captured-in-stack-closure.rs
index 6def5cf..e60f964 100644
--- a/src/test/debuginfo/var-captured-in-stack-closure.rs
+++ b/src/test/debuginfo/var-captured-in-stack-closure.rs
@@ -69,7 +69,7 @@
 // lldb-command:print *owned
 // lldb-check:[...]$9 = 6
 
-#![feature(unboxed_closures, box_syntax)]
+#![feature(box_syntax)]
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
diff --git a/src/test/compile-fail/feature-gate-rust-call.rs b/src/test/incremental/rlib_cross_crate/auxiliary/a.rs
similarity index 65%
rename from src/test/compile-fail/feature-gate-rust-call.rs
rename to src/test/incremental/rlib_cross_crate/auxiliary/a.rs
index 029a9ca..ff5fd63 100644
--- a/src/test/compile-fail/feature-gate-rust-call.rs
+++ b/src/test/incremental/rlib_cross_crate/auxiliary/a.rs
@@ -8,14 +8,18 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-extern "rust-call" fn foo() { } //~ ERROR rust-call ABI is subject to change
+// no-prefer-dynamic
 
-trait Foo {
-    extern "rust-call" fn foo();
-}
+#![crate_type="rlib"]
 
-impl Foo for i32 {
-    extern "rust-call" fn foo() { } //~ ERROR rust-call ABI is subject to change
-}
+#[cfg(rpass1)]
+pub type X = u32;
 
-fn main() { }
+#[cfg(rpass2)]
+pub type X = i32;
+
+// this version doesn't actually change anything:
+#[cfg(rpass3)]
+pub type X = i32;
+
+pub type Y = char;
diff --git a/src/test/incremental/rlib_cross_crate/b.rs b/src/test/incremental/rlib_cross_crate/b.rs
new file mode 100644
index 0000000..5539837
--- /dev/null
+++ b/src/test/incremental/rlib_cross_crate/b.rs
@@ -0,0 +1,38 @@
+// 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.
+
+// Same test as `type_alias_cross_crate`, but with
+// `no-prefer-dynamic`, ensuring that we test what happens when we
+// build rlibs (before we were only testing dylibs, which meant we
+// didn't realize we had to preserve a `bc` file as well).
+
+// aux-build:a.rs
+// revisions:rpass1 rpass2 rpass3
+// no-prefer-dynamic
+
+
+#![feature(rustc_attrs)]
+
+extern crate a;
+
+#[rustc_dirty(label="TypeckItemBody", cfg="rpass2")]
+#[rustc_clean(label="TypeckItemBody", cfg="rpass3")]
+pub fn use_X() -> u32 {
+    let x: a::X = 22;
+    x as u32
+}
+
+#[rustc_clean(label="TypeckItemBody", cfg="rpass2")]
+#[rustc_clean(label="TypeckItemBody", cfg="rpass3")]
+pub fn use_Y() {
+    let x: a::Y = 'c';
+}
+
+pub fn main() { }
diff --git a/src/test/incremental/spike-neg1.rs b/src/test/incremental/spike-neg1.rs
new file mode 100644
index 0000000..b00c68a
--- /dev/null
+++ b/src/test/incremental/spike-neg1.rs
@@ -0,0 +1,62 @@
+// 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.
+
+// A variant of the first "spike" test that serves to test the
+// `rustc_partition_reused` and `rustc_partition_translated` tests.
+// Here we change and say that the `x` module will be reused (when in
+// fact it will not), and then indicate that the test itself
+// should-fail (because an error will be reported, and hence the
+// revision rpass2 will not compile, despite being named rpass).
+
+// revisions:rpass1 rpass2
+// should-fail
+
+#![feature(rustc_attrs)]
+
+#![rustc_partition_reused(module="spike_neg1", cfg="rpass2")]
+#![rustc_partition_reused(module="spike_neg1-x", cfg="rpass2")] // this is wrong!
+#![rustc_partition_reused(module="spike_neg1-y", cfg="rpass2")]
+
+mod x {
+    pub struct X {
+        x: u32, y: u32,
+    }
+
+    #[cfg(rpass1)]
+    fn make() -> X {
+        X { x: 22, y: 0 }
+    }
+
+    #[cfg(rpass2)]
+    fn make() -> X {
+        X { x: 11, y: 11 }
+    }
+
+    pub fn new() -> X {
+        make()
+    }
+
+    pub fn sum(x: &X) -> u32 {
+        x.x + x.y
+    }
+}
+
+mod y {
+    use x;
+
+    pub fn assert_sum() -> bool {
+        let x = x::new();
+        x::sum(&x) == 22
+    }
+}
+
+pub fn main() {
+    y::assert_sum();
+}
diff --git a/src/test/incremental/spike-neg2.rs b/src/test/incremental/spike-neg2.rs
new file mode 100644
index 0000000..472d11d
--- /dev/null
+++ b/src/test/incremental/spike-neg2.rs
@@ -0,0 +1,62 @@
+// 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.
+
+// A variant of the first "spike" test that serves to test the
+// `rustc_partition_reused` and `rustc_partition_translated` tests.
+// Here we change and say that the `y` module will be translated (when
+// in fact it will not), and then indicate that the test itself
+// should-fail (because an error will be reported, and hence the
+// revision rpass2 will not compile, despite being named rpass).
+
+// revisions:rpass1 rpass2
+// should-fail
+
+#![feature(rustc_attrs)]
+
+#![rustc_partition_reused(module="spike_neg2", cfg="rpass2")]
+#![rustc_partition_translated(module="spike_neg2-x", cfg="rpass2")]
+#![rustc_partition_translated(module="spike_neg2-y", cfg="rpass2")] // this is wrong!
+
+mod x {
+    pub struct X {
+        x: u32, y: u32,
+    }
+
+    #[cfg(rpass1)]
+    fn make() -> X {
+        X { x: 22, y: 0 }
+    }
+
+    #[cfg(rpass2)]
+    fn make() -> X {
+        X { x: 11, y: 11 }
+    }
+
+    pub fn new() -> X {
+        make()
+    }
+
+    pub fn sum(x: &X) -> u32 {
+        x.x + x.y
+    }
+}
+
+mod y {
+    use x;
+
+    pub fn assert_sum() -> bool {
+        let x = x::new();
+        x::sum(&x) == 22
+    }
+}
+
+pub fn main() {
+    y::assert_sum();
+}
diff --git a/src/test/incremental/spike.rs b/src/test/incremental/spike.rs
new file mode 100644
index 0000000..68af20d
--- /dev/null
+++ b/src/test/incremental/spike.rs
@@ -0,0 +1,63 @@
+// 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.
+
+// A first "spike" for incremental compilation: here, we change the
+// content of the `make` function, and we find that we can reuse the
+// `y` module entirely (but not the `x` module).
+
+// revisions:rpass1 rpass2
+
+#![feature(rustc_attrs)]
+
+#![rustc_partition_reused(module="spike", cfg="rpass2")]
+#![rustc_partition_translated(module="spike-x", cfg="rpass2")]
+#![rustc_partition_reused(module="spike-y", cfg="rpass2")]
+
+mod x {
+    pub struct X {
+        x: u32, y: u32,
+    }
+
+    #[cfg(rpass1)]
+    fn make() -> X {
+        X { x: 22, y: 0 }
+    }
+
+    #[cfg(rpass2)]
+    fn make() -> X {
+        X { x: 11, y: 11 }
+    }
+
+    #[rustc_dirty(label="TypeckItemBody", cfg="rpass2")]
+    #[rustc_clean(label="ItemSignature", cfg="rpass2")]
+    pub fn new() -> X {
+        make()
+    }
+
+    #[rustc_clean(label="TypeckItemBody", cfg="rpass2")]
+    #[rustc_clean(label="ItemSignature", cfg="rpass2")]
+    pub fn sum(x: &X) -> u32 {
+        x.x + x.y
+    }
+}
+
+mod y {
+    use x;
+
+    #[rustc_clean(label="TypeckItemBody", cfg="rpass2")]
+    pub fn assert_sum() -> bool {
+        let x = x::new();
+        x::sum(&x) == 22
+    }
+}
+
+pub fn main() {
+    y::assert_sum();
+}
diff --git a/src/test/run-make/execution-engine/Makefile b/src/test/run-make/execution-engine/Makefile
deleted file mode 100644
index 4c818cd..0000000
--- a/src/test/run-make/execution-engine/Makefile
+++ /dev/null
@@ -1,21 +0,0 @@
--include ../tools.mk
-
-# FIXME: ignore freebsd
-# This is a basic test of LLVM ExecutionEngine functionality using compiled
-# Rust code built using the `rustc` crate.
-
-ifeq ($(filter executionengine,$(LLVM_COMPONENTS)),executionengine)
-
-ifneq ($(shell uname),FreeBSD)
-all:
-	$(RUSTC) test.rs
-	$(call RUN,test $(RUSTC))
-else
-all:
-
-endif
-
-else
-all:
-
-endif
diff --git a/src/test/run-make/execution-engine/test.rs b/src/test/run-make/execution-engine/test.rs
deleted file mode 100644
index 2e90b51..0000000
--- a/src/test/run-make/execution-engine/test.rs
+++ /dev/null
@@ -1,277 +0,0 @@
-// Copyright 2015 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.
-
-#![feature(rustc_private)]
-#![feature(libc)]
-
-extern crate libc;
-extern crate rustc;
-extern crate rustc_driver;
-extern crate rustc_lint;
-extern crate rustc_llvm as llvm;
-extern crate rustc_metadata;
-extern crate rustc_resolve;
-extern crate rustc_errors;
-extern crate rustc_errors as errors;
-#[macro_use] extern crate syntax;
-
-use std::ffi::{CStr, CString};
-use std::mem::transmute;
-use std::path::PathBuf;
-use std::rc::Rc;
-use std::thread::Builder;
-
-use rustc::dep_graph::DepGraph;
-use rustc::hir::map as ast_map;
-use rustc::middle::cstore::LinkagePreference;
-use rustc::ty;
-use rustc::session::config::{self, basic_options, build_configuration, Input, Options};
-use rustc::session::build_session;
-use rustc_driver::{driver, abort_on_err};
-use rustc_resolve::MakeGlobMap;
-use rustc_metadata::cstore::CStore;
-use libc::c_void;
-
-use rustc_errors::registry::Registry;
-
-fn main() {
-    // Currently trips an assertion on i686-msvc, presumably because the support
-    // in LLVM is a little young.
-    if cfg!(target_env = "msvc") && cfg!(target_arch = "x86") {
-        return
-    }
-
-    let program = r#"
-    #[no_mangle]
-    pub static TEST_STATIC: i32 = 42;
-    "#;
-
-    let program2 = r#"
-    #[no_mangle]
-    pub fn test_add(a: i32, b: i32) -> i32 { a + b }
-    "#;
-
-    let mut path = match std::env::args().nth(2) {
-        Some(path) => PathBuf::from(&path),
-        None => panic!("missing rustc path")
-    };
-
-    // Remove two segments from rustc path to get sysroot.
-    path.pop();
-    path.pop();
-
-    let mut ee = ExecutionEngine::new(program, path);
-
-    let test_static = match ee.get_global("TEST_STATIC") {
-        Some(g) => g as *const i32,
-        None => panic!("failed to get global")
-    };
-
-    assert_eq!(unsafe { *test_static }, 42);
-
-    ee.add_module(program2);
-
-    let test_add: fn(i32, i32) -> i32;
-
-    test_add = match ee.get_function("test_add") {
-        Some(f) => unsafe { transmute(f) },
-        None => panic!("failed to get function")
-    };
-
-    assert_eq!(test_add(1, 2), 3);
-}
-
-struct ExecutionEngine {
-    ee: llvm::ExecutionEngineRef,
-    modules: Vec<llvm::ModuleRef>,
-    sysroot: PathBuf,
-}
-
-impl ExecutionEngine {
-    pub fn new(program: &str, sysroot: PathBuf) -> ExecutionEngine {
-        let (llmod, deps) = compile_program(program, sysroot.clone())
-            .expect("failed to compile program");
-
-        let ee = unsafe { llvm::LLVMBuildExecutionEngine(llmod) };
-
-        if ee.is_null() {
-            panic!("Failed to create ExecutionEngine: {}", llvm_error());
-        }
-
-        let ee = ExecutionEngine{
-            ee: ee,
-            modules: vec![llmod],
-            sysroot: sysroot,
-        };
-
-        ee.load_deps(&deps);
-        ee
-    }
-
-    pub fn add_module(&mut self, program: &str) {
-        let (llmod, deps) = compile_program(program, self.sysroot.clone())
-            .expect("failed to compile program in add_module");
-
-        unsafe { llvm::LLVMExecutionEngineAddModule(self.ee, llmod); }
-
-        self.modules.push(llmod);
-        self.load_deps(&deps);
-    }
-
-    /// Returns a raw pointer to the named function.
-    pub fn get_function(&mut self, name: &str) -> Option<*const c_void> {
-        let s = CString::new(name.as_bytes()).unwrap();
-
-        for &m in &self.modules {
-            let fv = unsafe { llvm::LLVMGetNamedFunction(m, s.as_ptr()) };
-
-            if !fv.is_null() {
-                let fp = unsafe { llvm::LLVMGetPointerToGlobal(self.ee, fv) };
-
-                assert!(!fp.is_null());
-                return Some(fp);
-            }
-        }
-        None
-    }
-
-    /// Returns a raw pointer to the named global item.
-    pub fn get_global(&mut self, name: &str) -> Option<*const c_void> {
-        let s = CString::new(name.as_bytes()).unwrap();
-
-        for &m in &self.modules {
-            let gv = unsafe { llvm::LLVMGetNamedGlobal(m, s.as_ptr()) };
-
-            if !gv.is_null() {
-                let gp = unsafe { llvm::LLVMGetPointerToGlobal(self.ee, gv) };
-
-                assert!(!gp.is_null());
-                return Some(gp);
-            }
-        }
-        None
-    }
-
-    /// Loads all dependencies of compiled code.
-    /// Expects a series of paths to dynamic library files.
-    fn load_deps(&self, deps: &[PathBuf]) {
-        for path in deps {
-            let s = match path.as_os_str().to_str() {
-                Some(s) => s,
-                None => panic!(
-                    "Could not convert crate path to UTF-8 string: {:?}", path)
-            };
-            let cs = CString::new(s).unwrap();
-
-            let res = unsafe { llvm::LLVMRustLoadDynamicLibrary(cs.as_ptr()) };
-
-            if res == 0 {
-                panic!("Failed to load crate {:?}: {}",
-                    path.display(), llvm_error());
-            }
-        }
-    }
-}
-
-impl Drop for ExecutionEngine {
-    fn drop(&mut self) {
-        unsafe { llvm::LLVMDisposeExecutionEngine(self.ee) };
-    }
-}
-
-/// Returns last error from LLVM wrapper code.
-fn llvm_error() -> String {
-    String::from_utf8_lossy(
-        unsafe { CStr::from_ptr(llvm::LLVMRustGetLastError()).to_bytes() })
-        .into_owned()
-}
-
-fn build_exec_options(sysroot: PathBuf) -> Options {
-    let mut opts = basic_options();
-
-    // librustc derives sysroot from the executable name.
-    // Since we are not rustc, we must specify it.
-    opts.maybe_sysroot = Some(sysroot);
-
-    // Prefer faster build time
-    opts.optimize = config::OptLevel::No;
-
-    // Don't require a `main` function
-    opts.crate_types = vec![config::CrateTypeDylib];
-
-    opts
-}
-
-/// Compiles input up to phase 4, translation to LLVM.
-///
-/// Returns the LLVM `ModuleRef` and a series of paths to dynamic libraries
-/// for crates used in the given input.
-fn compile_program(input: &str, sysroot: PathBuf)
-                   -> Option<(llvm::ModuleRef, Vec<PathBuf>)> {
-    let input = Input::Str {
-        name: driver::anon_src(),
-        input: input.to_string(),
-    };
-    let thread = Builder::new().name("compile_program".to_string());
-
-    let handle = thread.spawn(move || {
-        let opts = build_exec_options(sysroot);
-        let dep_graph = DepGraph::new(opts.build_dep_graph());
-        let cstore = Rc::new(CStore::new(&dep_graph));
-        let sess = build_session(opts,
-                                 &dep_graph,
-                                 None,
-                                 Registry::new(&rustc::DIAGNOSTICS),
-                                 cstore.clone());
-        rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
-
-        let cfg = build_configuration(&sess);
-
-        let id = "input".to_string();
-
-        let krate = panictry!(driver::phase_1_parse_input(&sess, cfg, &input));
-
-        let driver::ExpansionResult { defs, analysis, resolutions, mut hir_forest, .. } = {
-            driver::phase_2_configure_and_expand(
-                &sess, &cstore, krate, &id, None, MakeGlobMap::No, |_| Ok(()),
-            ).expect("phase_2 returned `None`")
-        };
-
-        let arenas = ty::CtxtArenas::new();
-        let ast_map = ast_map::map_crate(&mut hir_forest, defs);
-
-        abort_on_err(driver::phase_3_run_analysis_passes(
-            &sess, ast_map, analysis, resolutions, &arenas, &id,
-            |tcx, mir_map, analysis, _| {
-
-            let trans = driver::phase_4_translate_to_llvm(tcx, mir_map.unwrap(), analysis);
-
-            let crates = tcx.sess.cstore.used_crates(LinkagePreference::RequireDynamic);
-
-            // Collect crates used in the session.
-            // Reverse order finds dependencies first.
-            let deps = crates.into_iter().rev()
-                .filter_map(|(_, p)| p).collect();
-
-            assert_eq!(trans.modules.len(), 1);
-            let llmod = trans.modules[0].llmod;
-
-            // Workaround because raw pointers do not impl Send
-            let modp = llmod as usize;
-
-            (modp, deps)
-        }), &sess)
-    }).unwrap();
-
-    match handle.join() {
-        Ok((llmod, deps)) => Some((llmod as llvm::ModuleRef, deps)),
-        Err(_) => None
-    }
-}
diff --git a/src/test/run-make/llvm-phase/test.rs b/src/test/run-make/llvm-phase/test.rs
index 402b5ed..19e410f 100644
--- a/src/test/run-make/llvm-phase/test.rs
+++ b/src/test/run-make/llvm-phase/test.rs
@@ -13,11 +13,13 @@
 extern crate rustc;
 extern crate rustc_driver;
 extern crate rustc_llvm;
+extern crate rustc_trans;
 #[macro_use] extern crate syntax;
 extern crate getopts;
 
 use rustc_driver::{CompilerCalls, Compilation};
 use rustc_driver::driver::CompileController;
+use rustc_trans::ModuleSource;
 use rustc::session::Session;
 use syntax::codemap::FileLoader;
 use std::io;
@@ -51,7 +53,10 @@
             state.session.abort_if_errors();
             let trans = state.trans.unwrap();
             assert_eq!(trans.modules.len(), 1);
-            let rs_llmod = trans.modules[0].llmod;
+            let rs_llmod = match trans.modules[0].source {
+                ModuleSource::Preexisting(_) => unimplemented!(),
+                ModuleSource::Translated(llvm) => llvm.llmod,
+            };
             unsafe { rustc_llvm::LLVMDumpModule(rs_llmod) };
         });
         cc
diff --git a/src/test/run-pass/coerce-match-calls.rs b/src/test/run-pass-valgrind/coerce-match-calls.rs
similarity index 100%
rename from src/test/run-pass/coerce-match-calls.rs
rename to src/test/run-pass-valgrind/coerce-match-calls.rs
diff --git a/src/test/run-pass/coerce-match.rs b/src/test/run-pass-valgrind/coerce-match.rs
similarity index 100%
rename from src/test/run-pass/coerce-match.rs
rename to src/test/run-pass-valgrind/coerce-match.rs
diff --git a/src/test/run-pass/assignability-trait.rs b/src/test/run-pass/assignability-trait.rs
index 0ee4600..c364240 100644
--- a/src/test/run-pass/assignability-trait.rs
+++ b/src/test/run-pass/assignability-trait.rs
@@ -12,9 +12,6 @@
 // making method calls, but only if there aren't any matches without
 // it.
 
-
-#![feature(unboxed_closures)]
-
 trait iterable<A> {
     fn iterate<F>(&self, blk: F) -> bool where F: FnMut(&A) -> bool;
 }
diff --git a/src/test/run-pass/associated-types-impl-redirect.rs b/src/test/run-pass/associated-types-impl-redirect.rs
index 4082580..3e34367 100644
--- a/src/test/run-pass/associated-types-impl-redirect.rs
+++ b/src/test/run-pass/associated-types-impl-redirect.rs
@@ -14,7 +14,7 @@
 // for `ByRef`. The right answer was to consider the result ambiguous
 // until more type information was available.
 
-#![feature(lang_items, unboxed_closures)]
+#![feature(lang_items)]
 #![no_implicit_prelude]
 
 use std::marker::Sized;
diff --git a/src/test/run-pass/associated-types-where-clause-impl-ambiguity.rs b/src/test/run-pass/associated-types-where-clause-impl-ambiguity.rs
index 082ad53..ef1225d 100644
--- a/src/test/run-pass/associated-types-where-clause-impl-ambiguity.rs
+++ b/src/test/run-pass/associated-types-where-clause-impl-ambiguity.rs
@@ -14,7 +14,7 @@
 // for `ByRef`. The right answer was to consider the result ambiguous
 // until more type information was available.
 
-#![feature(lang_items, unboxed_closures)]
+#![feature(lang_items)]
 #![no_implicit_prelude]
 
 use std::marker::Sized;
diff --git a/src/test/run-pass/auxiliary/issue-18711.rs b/src/test/run-pass/auxiliary/issue-18711.rs
index a29dcc0..c247c02 100644
--- a/src/test/run-pass/auxiliary/issue-18711.rs
+++ b/src/test/run-pass/auxiliary/issue-18711.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(unboxed_closures)]
 #![crate_type = "rlib"]
 
 pub fn inner<F>(f: F) -> F {
diff --git a/src/test/run-pass/auxiliary/unboxed-closures-cross-crate.rs b/src/test/run-pass/auxiliary/unboxed-closures-cross-crate.rs
index dac20dd..dc9798a 100644
--- a/src/test/run-pass/auxiliary/unboxed-closures-cross-crate.rs
+++ b/src/test/run-pass/auxiliary/unboxed-closures-cross-crate.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(unboxed_closures)]
-
 use std::ops::Add;
 
 #[inline]
diff --git a/src/test/run-pass/backtrace.rs b/src/test/run-pass/backtrace.rs
index ad38dc8..f1ce17c 100644
--- a/src/test/run-pass/backtrace.rs
+++ b/src/test/run-pass/backtrace.rs
@@ -46,19 +46,7 @@
 }
 
 fn expected(fn_name: &str) -> String {
-    // FIXME(#32481)
-    //
-    // On windows, we read the function name from debuginfo using some
-    // system APIs. For whatever reason, these APIs seem to use the
-    // "name" field, which is only the "relative" name, not the full
-    // name with namespace info, so we just see `foo` and not
-    // `backtrace::foo` as we see on linux (which uses the linkage
-    // name).
-    if cfg!(windows) && cfg!(target_env = "msvc") {
-        format!(" - {}", fn_name)
-    } else {
-        format!(" - backtrace::{}", fn_name)
-    }
+    format!(" - backtrace::{}", fn_name)
 }
 
 fn runtest(me: &str) {
diff --git a/src/test/run-pass/bare-fn-implements-fn-mut.rs b/src/test/run-pass/bare-fn-implements-fn-mut.rs
index e8118e9..30a11ca 100644
--- a/src/test/run-pass/bare-fn-implements-fn-mut.rs
+++ b/src/test/run-pass/bare-fn-implements-fn-mut.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(unboxed_closures)]
-
 use std::ops::FnMut;
 
 fn call_f<F:FnMut()>(mut f: F) {
diff --git a/src/test/run-pass/borrowck/borrowck-move-by-capture-ok.rs b/src/test/run-pass/borrowck/borrowck-move-by-capture-ok.rs
index bbc668f..158594d 100644
--- a/src/test/run-pass/borrowck/borrowck-move-by-capture-ok.rs
+++ b/src/test/run-pass/borrowck/borrowck-move-by-capture-ok.rs
@@ -11,7 +11,6 @@
 
 #![allow(unknown_features)]
 #![feature(box_syntax)]
-#![feature(unboxed_closures)]
 
 pub fn main() {
     let bar: Box<_> = box 3;
diff --git a/src/test/run-pass/capture-clauses-unboxed-closures.rs b/src/test/run-pass/capture-clauses-unboxed-closures.rs
index 5e7d5aa..e8a9dc7 100644
--- a/src/test/run-pass/capture-clauses-unboxed-closures.rs
+++ b/src/test/run-pass/capture-clauses-unboxed-closures.rs
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-#![feature(unboxed_closures)]
-
 fn each<'a,T,F:FnMut(&'a T)>(x: &'a [T], mut f: F) {
     for val in x {
         f(val)
diff --git a/src/test/run-pass/closure-bounds-can-capture-chan.rs b/src/test/run-pass/closure-bounds-can-capture-chan.rs
index dbbac8a..5268e85 100644
--- a/src/test/run-pass/closure-bounds-can-capture-chan.rs
+++ b/src/test/run-pass/closure-bounds-can-capture-chan.rs
@@ -10,8 +10,6 @@
 
 // pretty-expanded FIXME #23616
 
-#![feature(unboxed_closures)]
-
 use std::sync::mpsc::channel;
 
 fn foo<F:FnOnce()+Send>(blk: F) {
diff --git a/src/test/run-pass/closure-reform.rs b/src/test/run-pass/closure-reform.rs
index 0fa67e8..a37733b 100644
--- a/src/test/run-pass/closure-reform.rs
+++ b/src/test/run-pass/closure-reform.rs
@@ -11,8 +11,6 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
-#![feature(unboxed_closures)]
-
 fn call_it<F>(f: F)
     where F : FnOnce(String) -> String
 {
diff --git a/src/test/run-pass/hashmap-memory.rs b/src/test/run-pass/hashmap-memory.rs
index 4dae113..3f6f1aa 100644
--- a/src/test/run-pass/hashmap-memory.rs
+++ b/src/test/run-pass/hashmap-memory.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 #![allow(unknown_features)]
-#![feature(unboxed_closures, std_misc)]
+#![feature(std_misc)]
 
 /**
    A somewhat reduced test case to expose some Valgrind issues.
diff --git a/src/test/run-pass/hrtb-parse.rs b/src/test/run-pass/hrtb-parse.rs
index ecd0bc6..cdffaef 100644
--- a/src/test/run-pass/hrtb-parse.rs
+++ b/src/test/run-pass/hrtb-parse.rs
@@ -13,7 +13,6 @@
 
 // pretty-expanded FIXME #23616
 
-#![feature(unboxed_closures)]
 #![allow(unused_variables)]
 #![allow(dead_code)]
 
diff --git a/src/test/run-pass/hrtb-precedence-of-plus-where-clause.rs b/src/test/run-pass/hrtb-precedence-of-plus-where-clause.rs
index bc00a07..46ea256 100644
--- a/src/test/run-pass/hrtb-precedence-of-plus-where-clause.rs
+++ b/src/test/run-pass/hrtb-precedence-of-plus-where-clause.rs
@@ -10,8 +10,6 @@
 
 // pretty-expanded FIXME #23616
 
-#![feature(unboxed_closures)]
-
 // Test that `F : Fn(isize) -> isize + Send` is interpreted as two
 // distinct bounds on `F`.
 
diff --git a/src/test/run-pass/hrtb-precedence-of-plus.rs b/src/test/run-pass/hrtb-precedence-of-plus.rs
index 892f2f1..d93e52a 100644
--- a/src/test/run-pass/hrtb-precedence-of-plus.rs
+++ b/src/test/run-pass/hrtb-precedence-of-plus.rs
@@ -11,7 +11,6 @@
 // pretty-expanded FIXME #23616
 
 #![allow(unknown_features)]
-#![feature(unboxed_closures)]
 
 // Test that `Fn(isize) -> isize + 'static` parses as `(Fn(isize) -> isize) +
 // 'static` and not `Fn(isize) -> (isize + 'static)`. The latter would
diff --git a/src/test/run-pass/hrtb-trait-object-paren-notation.rs b/src/test/run-pass/hrtb-trait-object-paren-notation.rs
index fefbd00..5b9d4a8 100644
--- a/src/test/run-pass/hrtb-trait-object-paren-notation.rs
+++ b/src/test/run-pass/hrtb-trait-object-paren-notation.rs
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-#![feature(unboxed_closures)]
-
 // A basic test of using a higher-ranked trait bound.
 
 trait FnLike<A,R> {
diff --git a/src/test/run-pass/hrtb-unboxed-closure-trait.rs b/src/test/run-pass/hrtb-unboxed-closure-trait.rs
index 008e7dd..6666b61 100644
--- a/src/test/run-pass/hrtb-unboxed-closure-trait.rs
+++ b/src/test/run-pass/hrtb-unboxed-closure-trait.rs
@@ -10,8 +10,6 @@
 
 // Test HRTB used with the `Fn` trait.
 
-#![feature(unboxed_closures)]
-
 fn foo<F:Fn(&isize)>(f: F) {
     let x = 22;
     f(&x);
diff --git a/src/test/run-pass/ifmt.rs b/src/test/run-pass/ifmt.rs
index ed56519..8b5536d 100644
--- a/src/test/run-pass/ifmt.rs
+++ b/src/test/run-pass/ifmt.rs
@@ -70,15 +70,15 @@
     t!(format!("{}", '☃'), "☃");
     t!(format!("{}", 10), "10");
     t!(format!("{}", 10_usize), "10");
-    t!(format!("{:?}", '☃'), "'\\u{2603}'");
+    t!(format!("{:?}", '☃'), "'☃'");
     t!(format!("{:?}", 10), "10");
     t!(format!("{:?}", 10_usize), "10");
     t!(format!("{:?}", "true"), "\"true\"");
     t!(format!("{:?}", "foo\nbar"), "\"foo\\nbar\"");
     t!(format!("{:?}", "foo\n\"bar\"\r\n\'baz\'\t\\qux\\"),
        r#""foo\n\"bar\"\r\n\'baz\'\t\\qux\\""#);
-    t!(format!("{:?}", "foo\0bar\x01baz\u{3b1}q\u{75}x"),
-       r#""foo\u{0}bar\u{1}baz\u{3b1}qux""#);
+    t!(format!("{:?}", "foo\0bar\x01baz\u{7f}q\u{75}x"),
+       r#""foo\u{0}bar\u{1}baz\u{7f}qux""#);
     t!(format!("{:o}", 10_usize), "12");
     t!(format!("{:x}", 10_usize), "a");
     t!(format!("{:X}", 10_usize), "A");
diff --git a/src/test/run-pass/issue-10718.rs b/src/test/run-pass/issue-10718.rs
index 0a6e454..fedd94e 100644
--- a/src/test/run-pass/issue-10718.rs
+++ b/src/test/run-pass/issue-10718.rs
@@ -10,8 +10,6 @@
 
 // pretty-expanded FIXME #23616
 
-#![feature(unboxed_closures)]
-
 fn f<F:FnOnce()>(p: F) {
     p();
 }
diff --git a/src/test/run-pass/issue-14936.rs b/src/test/run-pass/issue-14936.rs
index 5f8e7cb..428d4e4 100644
--- a/src/test/run-pass/issue-14936.rs
+++ b/src/test/run-pass/issue-14936.rs
@@ -28,7 +28,8 @@
             unsafe {
                 asm!("mov ($1), $0"
                      : $output_constraint (*wrap(&mut x, "out", &mut history))
-                     : "r"(&wrap(y, "in", &mut history)));
+                     : "r"(&wrap(y, "in", &mut history))
+                     :: "volatile");
             }
             assert_eq!((x,y), (1,1));
             let b: &[_] = &["out", "in"];
diff --git a/src/test/run-pass/issue-16560.rs b/src/test/run-pass/issue-16560.rs
index 596f0d2..e91569f 100644
--- a/src/test/run-pass/issue-16560.rs
+++ b/src/test/run-pass/issue-16560.rs
@@ -10,8 +10,6 @@
 
 // ignore-emscripten no threads support
 
-#![feature(unboxed_closures)]
-
 use std::thread;
 use std::mem;
 
diff --git a/src/test/run-pass/issue-16668.rs b/src/test/run-pass/issue-16668.rs
index 786c701..0fd9965 100644
--- a/src/test/run-pass/issue-16668.rs
+++ b/src/test/run-pass/issue-16668.rs
@@ -11,7 +11,6 @@
 // ignore-pretty
 
 #![allow(unknown_features)]
-#![feature(unboxed_closures)]
 
 struct Parser<'a, I, O> {
     parse: Box<FnMut(I) -> Result<O, String> + 'a>
diff --git a/src/test/run-pass/issue-16774.rs b/src/test/run-pass/issue-16774.rs
index 627717a..9ec5910 100644
--- a/src/test/run-pass/issue-16774.rs
+++ b/src/test/run-pass/issue-16774.rs
@@ -12,7 +12,6 @@
 #![allow(unknown_features)]
 #![feature(box_syntax)]
 #![feature(box_patterns)]
-#![feature(unboxed_closures)]
 
 use std::ops::{Deref, DerefMut};
 
diff --git a/src/test/run-pass/issue-17816.rs b/src/test/run-pass/issue-17816.rs
index 8e3cb41..a9aa4cd 100644
--- a/src/test/run-pass/issue-17816.rs
+++ b/src/test/run-pass/issue-17816.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(unboxed_closures)]
-
 use std::marker::PhantomData;
 
 fn main() {
diff --git a/src/test/run-pass/issue-18652.rs b/src/test/run-pass/issue-18652.rs
index 8ab645e..cea0bea 100644
--- a/src/test/run-pass/issue-18652.rs
+++ b/src/test/run-pass/issue-18652.rs
@@ -12,9 +12,6 @@
 // once closure as an optimization by trans.  This used to hit an
 // incorrect assert.
 
-
-#![feature(unboxed_closures)]
-
 fn main() {
     let x = 2u8;
     let y = 3u8;
diff --git a/src/test/run-pass/issue-18685.rs b/src/test/run-pass/issue-18685.rs
index e4537e1..b569dbc 100644
--- a/src/test/run-pass/issue-18685.rs
+++ b/src/test/run-pass/issue-18685.rs
@@ -13,8 +13,6 @@
 
 // pretty-expanded FIXME #23616
 
-#![feature(unboxed_closures)]
-
 trait Tr {
     fn foo(&self);
 
diff --git a/src/test/run-pass/issue-18711.rs b/src/test/run-pass/issue-18711.rs
index 277ad32..8239d74 100644
--- a/src/test/run-pass/issue-18711.rs
+++ b/src/test/run-pass/issue-18711.rs
@@ -13,8 +13,6 @@
 
 // pretty-expanded FIXME #23616
 
-#![feature(unboxed_closures)]
-
 // aux-build:issue-18711.rs
 extern crate issue_18711 as issue;
 
diff --git a/src/test/run-pass/issue-19127.rs b/src/test/run-pass/issue-19127.rs
index c5eb506..8d16991 100644
--- a/src/test/run-pass/issue-19127.rs
+++ b/src/test/run-pass/issue-19127.rs
@@ -10,8 +10,6 @@
 
 // pretty-expanded FIXME #23616
 
-#![feature(unboxed_closures)]
-
 fn foo<T, F: FnOnce(T) -> T>(f: F) {}
 fn id<'a>(input: &'a u8) -> &'a u8 { input }
 
diff --git a/src/test/run-pass/issue-19135.rs b/src/test/run-pass/issue-19135.rs
index 5e6dd56..ca20981 100644
--- a/src/test/run-pass/issue-19135.rs
+++ b/src/test/run-pass/issue-19135.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(unboxed_closures)]
-
 use std::marker::PhantomData;
 
 #[derive(Debug)]
diff --git a/src/test/run-pass/issue-28950.rs b/src/test/run-pass/issue-28950.rs
index f01ce46..efce148 100644
--- a/src/test/run-pass/issue-28950.rs
+++ b/src/test/run-pass/issue-28950.rs
@@ -8,6 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// compile-flags: -Z orbit=off
+// (blows the stack with MIR trans and no optimizations)
+
 // Tests that the `vec!` macro does not overflow the stack when it is
 // given data larger than the stack.
 
diff --git a/src/test/run-pass/issue-34932.rs b/src/test/run-pass/issue-34932.rs
new file mode 100644
index 0000000..e83939e
--- /dev/null
+++ b/src/test/run-pass/issue-34932.rs
@@ -0,0 +1,23 @@
+// 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.
+
+// compile-flags:--test
+// rustc-env:RUSTC_BOOTSTRAP_KEY=
+// ignore-pretty : (#23623) problems when  ending with // comments
+
+#![cfg(any())] // This test should be configured away
+#![feature(rustc_attrs)] // Test that this is allowed on stable/beta
+#![feature(iter_arith_traits)] // Test that this is not unused
+#![deny(unused_features)]
+
+#[test]
+fn dummy() {
+    let () = "this should not reach type-checking";
+}
diff --git a/src/test/compile-fail/feature-gate-abi-vectorcall.rs b/src/test/run-pass/mir_cross_crate.rs
similarity index 60%
copy from src/test/compile-fail/feature-gate-abi-vectorcall.rs
copy to src/test/run-pass/mir_cross_crate.rs
index 79f3c8d..cc239d9 100644
--- a/src/test/compile-fail/feature-gate-abi-vectorcall.rs
+++ b/src/test/run-pass/mir_cross_crate.rs
@@ -8,12 +8,21 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-extern "vectorcall" {   //~ ERROR vectorcall is experimental and subject to change
-    fn bar();
-}
+// compile-flags: -Z orbit
+// Tests that -Z orbit affects functions from other crates.
 
-extern "vectorcall" fn baz() {  //~ ERROR vectorcall is experimental and subject to change
+#![feature(unsafe_no_drop_flag)]
+
+#[unsafe_no_drop_flag]
+struct Foo;
+
+impl Drop for Foo {
+    fn drop(&mut self) {
+        panic!("MIR trans is not enabled for mem::forget");
+    }
 }
 
 fn main() {
+    let x = Foo;
+    std::mem::forget(x);
 }
diff --git a/src/test/run-pass/mir_trans_calls.rs b/src/test/run-pass/mir_trans_calls.rs
index ca3294a..7ff684a 100644
--- a/src/test/run-pass/mir_trans_calls.rs
+++ b/src/test/run-pass/mir_trans_calls.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(rustc_attrs, unboxed_closures, fn_traits)]
+#![feature(rustc_attrs, fn_traits)]
 
 #[rustc_mir]
 fn test1(a: isize, b: (i32, i32), c: &[i32]) -> (isize, (i32, i32), &[i32]) {
diff --git a/src/test/run-pass/myriad-closures.rs b/src/test/run-pass/myriad-closures.rs
new file mode 100644
index 0000000..d2c9a5d
--- /dev/null
+++ b/src/test/run-pass/myriad-closures.rs
@@ -0,0 +1,48 @@
+// 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.
+
+// This test case tests whether we can handle code bases that contain a high
+// number of closures, something that needs special handling in the MingGW
+// toolchain.
+// See https://github.com/rust-lang/rust/issues/34793 for more information.
+
+// Expand something exponentially
+macro_rules! go_bacterial {
+    ($mac:ident) => ($mac!());
+    ($mac:ident 1 $($t:tt)*) => (
+        go_bacterial!($mac $($t)*);
+        go_bacterial!($mac $($t)*);
+    )
+}
+
+macro_rules! mk_closure {
+    () => ({
+        let c = |a: u32| a + 4;
+        let _ = c(2);
+    })
+}
+
+macro_rules! mk_fn {
+    () => {
+        {
+            fn function() {
+                // Make 16 closures
+                go_bacterial!(mk_closure 1 1 1 1);
+            }
+            let _ = function();
+        }
+    }
+}
+
+fn main() {
+    // Make 2^12 functions, each containing 16 closures,
+    // resulting in 2^16 closures overall.
+    go_bacterial!(mk_fn 1 1 1 1  1 1 1 1  1 1 1 1);
+}
diff --git a/src/test/run-pass/simd-upgraded.rs b/src/test/run-pass/simd-upgraded.rs
new file mode 100644
index 0000000..821a505
--- /dev/null
+++ b/src/test/run-pass/simd-upgraded.rs
@@ -0,0 +1,30 @@
+// 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.
+
+// Test that removed LLVM SIMD intrinsics continue
+// to work via the "AutoUpgrade" mechanism.
+
+#![feature(cfg_target_feature, repr_simd)]
+#![feature(platform_intrinsics, stmt_expr_attributes)]
+
+#[repr(simd)]
+#[derive(PartialEq, Debug)]
+struct i16x8(i16, i16, i16, i16, i16, i16, i16, i16);
+
+fn main() {
+    #[cfg(target_feature = "sse2")] unsafe {
+        extern "platform-intrinsic" {
+            fn x86_mm_min_epi16(x: i16x8, y: i16x8) -> i16x8;
+        }
+        assert_eq!(x86_mm_min_epi16(i16x8(0, 1, 2, 3, 4, 5, 6, 7),
+                                    i16x8(7, 6, 5, 4, 3, 2, 1, 0)),
+                                    i16x8(0, 1, 2, 3, 3, 2, 1, 0));
+    };
+}
diff --git a/src/test/run-pass/sync-send-iterators-in-libcore.rs b/src/test/run-pass/sync-send-iterators-in-libcore.rs
index 9317899..d12bdf1 100644
--- a/src/test/run-pass/sync-send-iterators-in-libcore.rs
+++ b/src/test/run-pass/sync-send-iterators-in-libcore.rs
@@ -67,7 +67,7 @@
 
 fn main() {
     // for char.rs
-    all_sync_send!("Я", escape_default, escape_unicode);
+    all_sync_send!("Я", escape_debug, escape_default, escape_unicode);
 
     // for iter.rs
     all_sync_send_mutable_ref!([1], iter);
diff --git a/src/test/run-pass/tcp-stress.rs b/src/test/run-pass/tcp-stress.rs
index dfc8649..0ba019c 100644
--- a/src/test/run-pass/tcp-stress.rs
+++ b/src/test/run-pass/tcp-stress.rs
@@ -21,6 +21,8 @@
 use std::time::Duration;
 use std::thread::{self, Builder};
 
+const TARGET_CNT: usize = 200;
+
 fn main() {
     // This test has a chance to time out, try to not let it time out
     thread::spawn(move|| -> () {
@@ -42,8 +44,9 @@
     });
 
     let (tx, rx) = channel();
+
     let mut spawned_cnt = 0;
-    for _ in 0..1000 {
+    for _ in 0..TARGET_CNT {
         let tx = tx.clone();
         let res = Builder::new().stack_size(64 * 1024).spawn(move|| {
             match TcpStream::connect(addr) {
@@ -66,6 +69,6 @@
     for _ in 0..spawned_cnt {
         rx.recv().unwrap();
     }
-    assert_eq!(spawned_cnt, 1000);
+    assert_eq!(spawned_cnt, TARGET_CNT);
     process::exit(0);
 }
diff --git a/src/test/run-pass/trait-bounds-in-arc.rs b/src/test/run-pass/trait-bounds-in-arc.rs
index 24dc73d..0de6fbc 100644
--- a/src/test/run-pass/trait-bounds-in-arc.rs
+++ b/src/test/run-pass/trait-bounds-in-arc.rs
@@ -16,7 +16,6 @@
 
 #![allow(unknown_features)]
 #![feature(box_syntax, std_misc)]
-#![feature(unboxed_closures)]
 
 use std::sync::Arc;
 use std::sync::mpsc::channel;
diff --git a/src/test/run-pass/type-id-higher-rank.rs b/src/test/run-pass/type-id-higher-rank.rs
index 3030833..c29fb5e 100644
--- a/src/test/run-pass/type-id-higher-rank.rs
+++ b/src/test/run-pass/type-id-higher-rank.rs
@@ -12,7 +12,7 @@
 // Also acts as a regression test for an ICE (issue #19791)
 
 
-#![feature(unboxed_closures, core)]
+#![feature(core)]
 
 use std::any::{Any, TypeId};
 
diff --git a/src/test/run-pass/unboxed-closures-all-traits.rs b/src/test/run-pass/unboxed-closures-all-traits.rs
index c28d4f4..201500d 100644
--- a/src/test/run-pass/unboxed-closures-all-traits.rs
+++ b/src/test/run-pass/unboxed-closures-all-traits.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-#![feature(lang_items, unboxed_closures)]
+#![feature(lang_items)]
 
 fn a<F:Fn(isize, isize) -> isize>(f: F) -> isize {
     f(1, 2)
diff --git a/src/test/run-pass/unboxed-closures-blanket-fn-mut.rs b/src/test/run-pass/unboxed-closures-blanket-fn-mut.rs
index 54c9290..23ec0cb 100644
--- a/src/test/run-pass/unboxed-closures-blanket-fn-mut.rs
+++ b/src/test/run-pass/unboxed-closures-blanket-fn-mut.rs
@@ -10,8 +10,7 @@
 
 // Test that you can supply `&F` where `F: FnMut()`.
 
-
-#![feature(lang_items, unboxed_closures)]
+#![feature(lang_items)]
 
 fn a<F:FnMut() -> i32>(mut f: F) -> i32 {
     f()
diff --git a/src/test/run-pass/unboxed-closures-blanket-fn.rs b/src/test/run-pass/unboxed-closures-blanket-fn.rs
index eb47447..2aa48e7 100644
--- a/src/test/run-pass/unboxed-closures-blanket-fn.rs
+++ b/src/test/run-pass/unboxed-closures-blanket-fn.rs
@@ -10,8 +10,7 @@
 
 // Test that you can supply `&F` where `F: Fn()`.
 
-
-#![feature(lang_items, unboxed_closures)]
+#![feature(lang_items)]
 
 fn a<F:Fn() -> i32>(f: F) -> i32 {
     f()
diff --git a/src/test/run-pass/unboxed-closures-boxed.rs b/src/test/run-pass/unboxed-closures-boxed.rs
index 5dea6a7..069f268 100644
--- a/src/test/run-pass/unboxed-closures-boxed.rs
+++ b/src/test/run-pass/unboxed-closures-boxed.rs
@@ -10,7 +10,6 @@
 
 #![allow(unknown_features)]
 #![feature(box_syntax)]
-#![feature(unboxed_closures)]
 
 use std::ops::FnMut;
 
diff --git a/src/test/run-pass/unboxed-closures-by-ref.rs b/src/test/run-pass/unboxed-closures-by-ref.rs
index e3ddfdb..b251215 100644
--- a/src/test/run-pass/unboxed-closures-by-ref.rs
+++ b/src/test/run-pass/unboxed-closures-by-ref.rs
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-#![feature(unboxed_closures)]
-
 // Test by-ref capture of environment in unboxed closure types
 
 fn call_fn<F: Fn()>(f: F) {
diff --git a/src/test/run-pass/unboxed-closures-call-fn-autoderef.rs b/src/test/run-pass/unboxed-closures-call-fn-autoderef.rs
index 64236ce..56c53bc 100644
--- a/src/test/run-pass/unboxed-closures-call-fn-autoderef.rs
+++ b/src/test/run-pass/unboxed-closures-call-fn-autoderef.rs
@@ -10,9 +10,6 @@
 
 // Test that the call operator autoderefs when calling a bounded type parameter.
 
-
-#![feature(unboxed_closures)]
-
 use std::ops::FnMut;
 
 fn call_with_2(x: &fn(isize) -> isize) -> isize
diff --git a/src/test/run-pass/unboxed-closures-call-sugar-autoderef.rs b/src/test/run-pass/unboxed-closures-call-sugar-autoderef.rs
index 67ab84f..63667ec 100644
--- a/src/test/run-pass/unboxed-closures-call-sugar-autoderef.rs
+++ b/src/test/run-pass/unboxed-closures-call-sugar-autoderef.rs
@@ -10,9 +10,6 @@
 
 // Test that the call operator autoderefs when calling a bounded type parameter.
 
-
-#![feature(unboxed_closures)]
-
 use std::ops::FnMut;
 
 fn call_with_2<F>(x: &mut F) -> isize
diff --git a/src/test/run-pass/unboxed-closures-call-sugar-object-autoderef.rs b/src/test/run-pass/unboxed-closures-call-sugar-object-autoderef.rs
index c820262..a92fb05 100644
--- a/src/test/run-pass/unboxed-closures-call-sugar-object-autoderef.rs
+++ b/src/test/run-pass/unboxed-closures-call-sugar-object-autoderef.rs
@@ -11,7 +11,6 @@
 // Test that the call operator autoderefs when calling to an object type.
 
 #![allow(unknown_features)]
-#![feature(unboxed_closures)]
 
 use std::ops::FnMut;
 
diff --git a/src/test/run-pass/unboxed-closures-call-sugar-object.rs b/src/test/run-pass/unboxed-closures-call-sugar-object.rs
index 629da10..5dd2343 100644
--- a/src/test/run-pass/unboxed-closures-call-sugar-object.rs
+++ b/src/test/run-pass/unboxed-closures-call-sugar-object.rs
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 #![allow(unknown_features)]
-#![feature(unboxed_closures)]
 
 use std::ops::FnMut;
 
diff --git a/src/test/run-pass/unboxed-closures-counter-not-moved.rs b/src/test/run-pass/unboxed-closures-counter-not-moved.rs
index cb5f190..0b85916 100644
--- a/src/test/run-pass/unboxed-closures-counter-not-moved.rs
+++ b/src/test/run-pass/unboxed-closures-counter-not-moved.rs
@@ -10,7 +10,6 @@
 
 // Test that we mutate a counter on the stack only when we expect to.
 
-
 fn call<F>(f: F) where F : FnOnce() {
     f();
 }
diff --git a/src/test/run-pass/unboxed-closures-direct-sugary-call.rs b/src/test/run-pass/unboxed-closures-direct-sugary-call.rs
index c91aa6e..c8da4a6 100644
--- a/src/test/run-pass/unboxed-closures-direct-sugary-call.rs
+++ b/src/test/run-pass/unboxed-closures-direct-sugary-call.rs
@@ -10,8 +10,6 @@
 
 // pretty-expanded FIXME #23616
 
-#![feature(unboxed_closures)]
-
 fn main() {
     let mut unboxed = || {};
     unboxed();
diff --git a/src/test/run-pass/unboxed-closures-drop.rs b/src/test/run-pass/unboxed-closures-drop.rs
index 78f4905..57f2f87 100644
--- a/src/test/run-pass/unboxed-closures-drop.rs
+++ b/src/test/run-pass/unboxed-closures-drop.rs
@@ -11,9 +11,6 @@
 // A battery of tests to ensure destructors of unboxed closure environments
 // run at the right times.
 
-
-#![feature(unboxed_closures)]
-
 static mut DROP_COUNT: usize = 0;
 
 fn drop_count() -> usize {
diff --git a/src/test/run-pass/unboxed-closures-extern-fn.rs b/src/test/run-pass/unboxed-closures-extern-fn.rs
index 57acbae..eddb608 100644
--- a/src/test/run-pass/unboxed-closures-extern-fn.rs
+++ b/src/test/run-pass/unboxed-closures-extern-fn.rs
@@ -10,10 +10,6 @@
 
 // Checks that extern fn pointers implement the full range of Fn traits.
 
-
-#![feature(unboxed_closures)]
-#![feature(unboxed_closures)]
-
 use std::ops::{Fn,FnMut,FnOnce};
 
 fn square(x: isize) -> isize { x * x }
diff --git a/src/test/run-pass/unboxed-closures-fn-as-fnmut-and-fnonce.rs b/src/test/run-pass/unboxed-closures-fn-as-fnmut-and-fnonce.rs
index 2e63c60..f90aced 100644
--- a/src/test/run-pass/unboxed-closures-fn-as-fnmut-and-fnonce.rs
+++ b/src/test/run-pass/unboxed-closures-fn-as-fnmut-and-fnonce.rs
@@ -11,7 +11,6 @@
 // Checks that the Fn trait hierarchy rules permit
 // any Fn trait to be used where Fn is implemented.
 
-
 #![feature(unboxed_closures, fn_traits)]
 
 use std::ops::{Fn,FnMut,FnOnce};
diff --git a/src/test/run-pass/unboxed-closures-fnmut-as-fnonce.rs b/src/test/run-pass/unboxed-closures-fnmut-as-fnonce.rs
index ce93fcaf..0a977ce 100644
--- a/src/test/run-pass/unboxed-closures-fnmut-as-fnonce.rs
+++ b/src/test/run-pass/unboxed-closures-fnmut-as-fnonce.rs
@@ -11,7 +11,6 @@
 // Checks that the Fn trait hierarchy rules permit
 // FnMut or FnOnce to be used where FnMut is implemented.
 
-
 #![feature(unboxed_closures, fn_traits)]
 
 struct S;
diff --git a/src/test/run-pass/unboxed-closures-generic.rs b/src/test/run-pass/unboxed-closures-generic.rs
index 47936ba..01c81ef 100644
--- a/src/test/run-pass/unboxed-closures-generic.rs
+++ b/src/test/run-pass/unboxed-closures-generic.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(unboxed_closures)]
-
 use std::ops::FnMut;
 
 fn call_it<F:FnMut(i32,i32)->i32>(y: i32, mut f: F) -> i32 {
diff --git a/src/test/run-pass/unboxed-closures-infer-fnmut-calling-fnmut.rs b/src/test/run-pass/unboxed-closures-infer-fnmut-calling-fnmut.rs
index 2da899e..1783303 100644
--- a/src/test/run-pass/unboxed-closures-infer-fnmut-calling-fnmut.rs
+++ b/src/test/run-pass/unboxed-closures-infer-fnmut-calling-fnmut.rs
@@ -11,7 +11,6 @@
 // Test that we are able to infer a suitable kind for this closure
 // that is just called (`FnMut`).
 
-
 fn main() {
     let mut counter = 0;
 
diff --git a/src/test/run-pass/unboxed-closures-infer-fnmut-move.rs b/src/test/run-pass/unboxed-closures-infer-fnmut-move.rs
index 32fc343..7945272 100644
--- a/src/test/run-pass/unboxed-closures-infer-fnmut-move.rs
+++ b/src/test/run-pass/unboxed-closures-infer-fnmut-move.rs
@@ -11,7 +11,6 @@
 // Test that we are able to infer a suitable kind for this `move`
 // closure that is just called (`FnMut`).
 
-
 fn main() {
     let mut counter = 0;
 
diff --git a/src/test/run-pass/unboxed-closures-infer-fnmut.rs b/src/test/run-pass/unboxed-closures-infer-fnmut.rs
index a8469f4..67f36b9 100644
--- a/src/test/run-pass/unboxed-closures-infer-fnmut.rs
+++ b/src/test/run-pass/unboxed-closures-infer-fnmut.rs
@@ -11,7 +11,6 @@
 // Test that we are able to infer a suitable kind for this closure
 // that is just called (`FnMut`).
 
-
 fn main() {
     let mut counter = 0;
 
diff --git a/src/test/run-pass/unboxed-closures-infer-kind.rs b/src/test/run-pass/unboxed-closures-infer-kind.rs
index fa66847..c04df7e 100644
--- a/src/test/run-pass/unboxed-closures-infer-kind.rs
+++ b/src/test/run-pass/unboxed-closures-infer-kind.rs
@@ -11,9 +11,6 @@
 // Test that we can infer the "kind" of an unboxed closure based on
 // the expected type.
 
-
-#![feature(unboxed_closures)]
-
 // Test by-ref capture of environment in unboxed closure types
 
 fn call_fn<F: Fn()>(f: F) {
diff --git a/src/test/run-pass/unboxed-closures-infer-upvar.rs b/src/test/run-pass/unboxed-closures-infer-upvar.rs
index f242314..1401fe7 100644
--- a/src/test/run-pass/unboxed-closures-infer-upvar.rs
+++ b/src/test/run-pass/unboxed-closures-infer-upvar.rs
@@ -11,7 +11,6 @@
 // Test that the type variable in the type(`Vec<_>`) of a closed over
 // variable does not interfere with type inference.
 
-
 fn f<F: FnMut()>(mut f: F) {
     f();
 }
diff --git a/src/test/run-pass/unboxed-closures-move-mutable.rs b/src/test/run-pass/unboxed-closures-move-mutable.rs
index 1aca317..a55b0a0 100644
--- a/src/test/run-pass/unboxed-closures-move-mutable.rs
+++ b/src/test/run-pass/unboxed-closures-move-mutable.rs
@@ -10,7 +10,6 @@
 
 // pretty-expanded FIXME #23616
 
-#![feature(unboxed_closures)]
 #![deny(unused_mut)]
 
 // Test that mutating a mutable upvar in a capture-by-value unboxed
diff --git a/src/test/run-pass/unboxed-closures-move-some-upvars-in-by-ref-closure.rs b/src/test/run-pass/unboxed-closures-move-some-upvars-in-by-ref-closure.rs
index e2b2867..9966364 100644
--- a/src/test/run-pass/unboxed-closures-move-some-upvars-in-by-ref-closure.rs
+++ b/src/test/run-pass/unboxed-closures-move-some-upvars-in-by-ref-closure.rs
@@ -11,7 +11,6 @@
 // Test that in a by-ref once closure we move some variables even as
 // we capture others by mutable reference.
 
-
 fn call<F>(f: F) where F : FnOnce() {
     f();
 }
diff --git a/src/test/run-pass/unboxed-closures-simple.rs b/src/test/run-pass/unboxed-closures-simple.rs
index ec34198..429afb9 100644
--- a/src/test/run-pass/unboxed-closures-simple.rs
+++ b/src/test/run-pass/unboxed-closures-simple.rs
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-#![feature(unboxed_closures)]
-
 use std::ops::FnMut;
 
 pub fn main() {
diff --git a/src/test/run-pass/unboxed-closures-single-word-env.rs b/src/test/run-pass/unboxed-closures-single-word-env.rs
index 166054e..3ed055a 100644
--- a/src/test/run-pass/unboxed-closures-single-word-env.rs
+++ b/src/test/run-pass/unboxed-closures-single-word-env.rs
@@ -11,9 +11,6 @@
 // Ensures that single-word environments work right in unboxed closures.
 // These take a different path in codegen.
 
-
-#![feature(unboxed_closures)]
-
 fn a<F:Fn(isize, isize) -> isize>(f: F) -> isize {
     f(1, 2)
 }
diff --git a/src/test/run-pass/unboxed-closures-static-call-fn-once.rs b/src/test/run-pass/unboxed-closures-static-call-fn-once.rs
index e90a344..c13e951 100644
--- a/src/test/run-pass/unboxed-closures-static-call-fn-once.rs
+++ b/src/test/run-pass/unboxed-closures-static-call-fn-once.rs
@@ -10,8 +10,6 @@
 
 // pretty-expanded FIXME #23616
 
-#![feature(unboxed_closures)]
-
 fn main() {
     let onetime = |x| x;
     onetime(0);
diff --git a/src/test/run-pass/unboxed-closures-sugar-object.rs b/src/test/run-pass/unboxed-closures-sugar-object.rs
index 49b9b7f..b7d367f 100644
--- a/src/test/run-pass/unboxed-closures-sugar-object.rs
+++ b/src/test/run-pass/unboxed-closures-sugar-object.rs
@@ -10,9 +10,7 @@
 
 // Test unboxed closure sugar used in object types.
 
-
 #![allow(dead_code)]
-#![feature(unboxed_closures)]
 
 struct Foo<T,U> {
     t: T, u: U
diff --git a/src/test/run-pass/unboxed-closures-unique-type-id.rs b/src/test/run-pass/unboxed-closures-unique-type-id.rs
index 30c45fc..40071ec 100644
--- a/src/test/run-pass/unboxed-closures-unique-type-id.rs
+++ b/src/test/run-pass/unboxed-closures-unique-type-id.rs
@@ -19,9 +19,6 @@
 //
 // compile-flags: -g
 
-
-#![feature(unboxed_closures)]
-
 use std::ptr;
 
 pub fn replace_map<'a, T, F>(src: &mut T, prod: F) where F: FnOnce(T) -> T {
diff --git a/src/test/run-pass/unboxed-closures-zero-args.rs b/src/test/run-pass/unboxed-closures-zero-args.rs
index cb3a18a..9e6a7cc 100644
--- a/src/test/run-pass/unboxed-closures-zero-args.rs
+++ b/src/test/run-pass/unboxed-closures-zero-args.rs
@@ -10,8 +10,6 @@
 
 // pretty-expanded FIXME #23616
 
-#![feature(unboxed_closures)]
-
 fn main() {
     let mut zero = || {};
     let () = zero();
diff --git a/src/test/run-pass/where-clauses-unboxed-closures.rs b/src/test/run-pass/where-clauses-unboxed-closures.rs
index c509cbe..8a775ca 100644
--- a/src/test/run-pass/where-clauses-unboxed-closures.rs
+++ b/src/test/run-pass/where-clauses-unboxed-closures.rs
@@ -10,8 +10,6 @@
 
 // pretty-expanded FIXME #23616
 
-#![feature(unboxed_closures)]
-
 struct Bencher;
 
 // ICE
diff --git a/src/test/compile-fail/feature-gate-abi-vectorcall.rs b/src/test/rustdoc/issue-34928.rs
similarity index 68%
copy from src/test/compile-fail/feature-gate-abi-vectorcall.rs
copy to src/test/rustdoc/issue-34928.rs
index 79f3c8d..b2104a0 100644
--- a/src/test/compile-fail/feature-gate-abi-vectorcall.rs
+++ b/src/test/rustdoc/issue-34928.rs
@@ -8,12 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-extern "vectorcall" {   //~ ERROR vectorcall is experimental and subject to change
-    fn bar();
-}
+#![crate_name = "foo"]
 
-extern "vectorcall" fn baz() {  //~ ERROR vectorcall is experimental and subject to change
-}
+pub trait Bar {}
 
-fn main() {
-}
+// @has foo/struct.Foo.html '//pre' 'pub struct Foo<T>(pub T) where T: Bar;'
+pub struct Foo<T>(pub T) where T: Bar;
diff --git a/src/test/rustdoc/where.rs b/src/test/rustdoc/where.rs
index 91ec69d..d8dc115 100644
--- a/src/test/rustdoc/where.rs
+++ b/src/test/rustdoc/where.rs
@@ -12,7 +12,7 @@
 
 pub trait MyTrait { fn dummy(&self) { } }
 
-// @has foo/struct.Alpha.html '//pre' "pub struct Alpha<A> where A: MyTrait"
+// @has foo/struct.Alpha.html '//pre' "pub struct Alpha<A>(_) where A: MyTrait"
 pub struct Alpha<A>(A) where A: MyTrait;
 // @has foo/trait.Bravo.html '//pre' "pub trait Bravo<B> where B: MyTrait"
 pub trait Bravo<B> where B: MyTrait { fn get(&self, B: B); }
diff --git a/src/test/ui/codemap_tests/two_files.stderr b/src/test/ui/codemap_tests/two_files.stderr
index 6c388cd..cf3f187 100644
--- a/src/test/ui/codemap_tests/two_files.stderr
+++ b/src/test/ui/codemap_tests/two_files.stderr
@@ -2,12 +2,9 @@
   --> $DIR/two_files.rs:16:6
    |
 16 | impl Bar for Baz { }
-   |      ^^^ `Bar` is not a trait
-   | 
-  ::: $DIR/two_files_data.rs
+   |      ^^^
    |
-15 | type Bar = Foo;
-   | --------------- type aliases cannot be used for traits
+   = note: type aliases cannot be used for traits
 
 error: cannot continue compilation due to previous error
 
diff --git a/src/test/ui/mismatched_types/issue-26480.stderr b/src/test/ui/mismatched_types/issue-26480.stderr
index ff6920d..45638a6 100644
--- a/src/test/ui/mismatched_types/issue-26480.stderr
+++ b/src/test/ui/mismatched_types/issue-26480.stderr
@@ -5,7 +5,7 @@
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected u64, found usize
 $DIR/issue-26480.rs:38:5: 38:19 note: in this expansion of write! (defined in $DIR/issue-26480.rs)
 
-error: non-scalar cast: `_` as `()`
+error: non-scalar cast: `{integer}` as `()`
   --> $DIR/issue-26480.rs:33:19
    |
 33 |     ($x:expr) => ($x as ())