about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bootstrap/bootstrap.py14
-rw-r--r--src/bootstrap/build/cc.rs1
-rw-r--r--src/bootstrap/build/check.rs128
-rw-r--r--src/bootstrap/build/config.rs4
-rw-r--r--src/bootstrap/build/dist.rs4
-rw-r--r--src/bootstrap/build/mod.rs12
-rw-r--r--src/bootstrap/build/native.rs8
-rw-r--r--src/bootstrap/build/sanity.rs4
-rw-r--r--src/bootstrap/build/step.rs118
-rw-r--r--src/bootstrap/mk/Makefile.in5
-rw-r--r--src/libcore/intrinsics.rs6
-rw-r--r--src/librustc/dep_graph/thread.rs2
-rw-r--r--src/librustc/traits/error_reporting.rs3
-rw-r--r--src/librustc/traits/mod.rs3
-rw-r--r--src/librustc_data_structures/indexed_vec.rs6
-rw-r--r--src/librustc_data_structures/obligation_forest/mod.rs35
-rw-r--r--src/librustc_data_structures/obligation_forest/test.rs40
-rw-r--r--src/librustc_metadata/Cargo.toml1
-rw-r--r--src/librustc_metadata/astencode.rs20
-rw-r--r--src/librustc_metadata/common.rs4
-rw-r--r--src/librustc_metadata/creader.rs103
-rw-r--r--src/librustc_metadata/csearch.rs3
-rw-r--r--src/librustc_metadata/cstore.rs80
-rw-r--r--src/librustc_metadata/decoder.rs36
-rw-r--r--src/librustc_metadata/encoder.rs34
-rw-r--r--src/librustc_metadata/lib.rs1
-rw-r--r--src/librustc_metadata/loader.rs61
-rw-r--r--src/librustc_trans/diagnostics.rs38
-rw-r--r--src/librustc_trans/intrinsic.rs12
-rw-r--r--src/librustc_trans/monomorphize.rs3
-rw-r--r--src/librustc_typeck/check/intrinsic.rs2
-rw-r--r--src/librustc_typeck/check/mod.rs1
-rw-r--r--src/libstd/path.rs1
-rw-r--r--src/libsyntax/attr.rs105
-rw-r--r--src/libsyntax/diagnostic_list.rs54
-rw-r--r--src/libsyntax/feature_gate.rs17
-rw-r--r--src/libsyntax/lib.rs21
-rw-r--r--src/rustc/Cargo.lock1
-rw-r--r--src/test/compile-fail/changing-crates.rs2
-rw-r--r--src/test/compile-fail/const-unsized.rs35
-rw-r--r--src/test/compile-fail/intrinsic-return-address.rs24
-rw-r--r--src/test/compile-fail/issue-24446.rs2
-rw-r--r--src/test/compile-fail/stability-attribute-sanity.rs49
-rw-r--r--src/test/compile-fail/svh-change-lit.rs2
-rw-r--r--src/test/compile-fail/svh-change-significant-cfg.rs2
-rw-r--r--src/test/compile-fail/svh-change-trait-bound.rs2
-rw-r--r--src/test/compile-fail/svh-change-type-arg.rs2
-rw-r--r--src/test/compile-fail/svh-change-type-ret.rs2
-rw-r--r--src/test/compile-fail/svh-change-type-static.rs2
-rw-r--r--src/test/compile-fail/svh-use-trait.rs2
-rw-r--r--src/test/run-make/many-crates-but-no-match/Makefile2
-rw-r--r--src/test/run-pass/intrinsic-return-address.rs43
-rw-r--r--src/test/run-pass/issue-34503.rs20
-rw-r--r--src/tools/compiletest/src/runtest.rs20
-rw-r--r--src/tools/linkchecker/main.rs43
55 files changed, 914 insertions, 331 deletions
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 7b0a5d6b6df..33de8fd0107 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -10,6 +10,7 @@
 
 import argparse
 import contextlib
+import datetime
 import hashlib
 import os
 import shutil
@@ -18,6 +19,8 @@ import sys
 import tarfile
 import tempfile
 
+from time import time
+
 
 def get(url, path, verbose=False):
     sha_url = url + ".sha256"
@@ -118,6 +121,9 @@ def stage0_data(rust_root):
             data[a] = b
     return data
 
+def format_build_time(duration):
+    return str(datetime.timedelta(seconds=int(duration)))
+
 class RustBuild:
     def download_stage0(self):
         cache_dst = os.path.join(self.build_dir, "cache")
@@ -265,7 +271,7 @@ class RustBuild:
         try:
             ostype = subprocess.check_output(['uname', '-s']).strip()
             cputype = subprocess.check_output(['uname', '-m']).strip()
-        except subprocess.CalledProcessError:
+        except (subprocess.CalledProcessError, WindowsError):
             if sys.platform == 'win32':
                 return 'x86_64-pc-windows-msvc'
             err = "uname not found"
@@ -372,6 +378,8 @@ def main():
     rb._rustc_channel, rb._rustc_date = data['rustc'].split('-', 1)
     rb._cargo_channel, rb._cargo_date = data['cargo'].split('-', 1)
 
+    start_time = time()
+
     # Fetch/build the bootstrap
     rb.build = rb.build_triple()
     rb.download_stage0()
@@ -390,5 +398,9 @@ def main():
     env["BOOTSTRAP_PARENT_ID"] = str(os.getpid())
     rb.run(args, env)
 
+    end_time = time()
+
+    print("Build completed in %s" % format_build_time(end_time - start_time))
+
 if __name__ == '__main__':
     main()
diff --git a/src/bootstrap/build/cc.rs b/src/bootstrap/build/cc.rs
index 7eb50b8b86d..ff0941a97dc 100644
--- a/src/bootstrap/build/cc.rs
+++ b/src/bootstrap/build/cc.rs
@@ -90,6 +90,7 @@ fn set_compiler(cfg: &mut gcc::Config,
         // compiler already takes into account the triple in question.
         t if t.contains("android") => {
             if let Some(ndk) = config.and_then(|c| c.ndk.as_ref()) {
+                let target = target.replace("armv7", "arm");
                 let compiler = format!("{}-{}", target, gnu_compiler);
                 cfg.compiler(ndk.join("bin").join(compiler));
             }
diff --git a/src/bootstrap/build/check.rs b/src/bootstrap/build/check.rs
index 154d9556fd7..0a096f8e4de 100644
--- a/src/bootstrap/build/check.rs
+++ b/src/bootstrap/build/check.rs
@@ -23,6 +23,9 @@ use build_helper::output;
 use bootstrap::{dylib_path, dylib_path_var};
 
 use build::{Build, Compiler, Mode};
+use build::util;
+
+const ADB_TEST_DIR: &'static str = "/data/tmp";
 
 /// Runs the `linkchecker` tool as compiled in `stage` by the `host` compiler.
 ///
@@ -88,6 +91,7 @@ pub fn compiletest(build: &Build,
                    target: &str,
                    mode: &str,
                    suite: &str) {
+    println!("Check compiletest {} ({} -> {})", suite, compiler.host, target);
     let mut cmd = build.tool_cmd(compiler, "compiletest");
 
     // compiletest currently has... a lot of arguments, so let's just pass all
@@ -105,21 +109,23 @@ pub fn compiletest(build: &Build,
     cmd.arg("--host").arg(compiler.host);
     cmd.arg("--llvm-filecheck").arg(build.llvm_filecheck(&build.config.build));
 
-    let mut flags = format!("-Crpath");
+    let mut flags = vec!["-Crpath".to_string()];
     if build.config.rust_optimize_tests {
-        flags.push_str(" -O");
+        flags.push("-O".to_string());
     }
     if build.config.rust_debuginfo_tests {
-        flags.push_str(" -g");
+        flags.push("-g".to_string());
     }
 
-    cmd.arg("--host-rustcflags").arg(&flags);
-
-    let linkflag = format!("-Lnative={}", build.test_helpers_out(target).display());
-    cmd.arg("--target-rustcflags").arg(format!("{} {}", flags, linkflag));
+    let mut hostflags = build.rustc_flags(&compiler.host);
+    hostflags.extend(flags.clone());
+    cmd.arg("--host-rustcflags").arg(hostflags.join(" "));
 
-    // FIXME: needs android support
-    cmd.arg("--android-cross-path").arg("");
+    let mut targetflags = build.rustc_flags(&target);
+    targetflags.extend(flags);
+    targetflags.push(format!("-Lnative={}",
+                             build.test_helpers_out(target).display()));
+    cmd.arg("--target-rustcflags").arg(targetflags.join(" "));
 
     // FIXME: CFG_PYTHON should probably be detected more robustly elsewhere
     let python_default = "python";
@@ -180,6 +186,16 @@ pub fn compiletest(build: &Build,
     }
     build.add_bootstrap_key(compiler, &mut cmd);
 
+    cmd.arg("--adb-path").arg("adb");
+    cmd.arg("--adb-test-dir").arg(ADB_TEST_DIR);
+    if target.contains("android") {
+        // Assume that cc for this target comes from the android sysroot
+        cmd.arg("--android-cross-path")
+           .arg(build.cc(target).parent().unwrap().parent().unwrap());
+    } else {
+        cmd.arg("--android-cross-path").arg("");
+    }
+
     build.run(&mut cmd);
 }
 
@@ -302,7 +318,97 @@ pub fn krate(build: &Build,
     let mut dylib_path = dylib_path();
     dylib_path.insert(0, build.sysroot_libdir(compiler, target));
     cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
-    cargo.args(&build.flags.args);
 
-    build.run(&mut cargo);
+    if target.contains("android") {
+        build.run(cargo.arg("--no-run"));
+        krate_android(build, compiler, target, mode);
+    } else {
+        cargo.args(&build.flags.args);
+        build.run(&mut cargo);
+    }
+}
+
+fn krate_android(build: &Build,
+                 compiler: &Compiler,
+                 target: &str,
+                 mode: Mode) {
+    let mut tests = Vec::new();
+    let out_dir = build.cargo_out(compiler, mode, target);
+    find_tests(&out_dir, target, &mut tests);
+    find_tests(&out_dir.join("deps"), target, &mut tests);
+
+    for test in tests {
+        build.run(Command::new("adb").arg("push").arg(&test).arg(ADB_TEST_DIR));
+
+        let test_file_name = test.file_name().unwrap().to_string_lossy();
+        let log = format!("{}/check-stage{}-T-{}-H-{}-{}.log",
+                          ADB_TEST_DIR,
+                          compiler.stage,
+                          target,
+                          compiler.host,
+                          test_file_name);
+        let program = format!("(cd {dir}; \
+                                LD_LIBRARY_PATH=./{target} ./{test} \
+                                    --logfile {log} \
+                                    {args})",
+                              dir = ADB_TEST_DIR,
+                              target = target,
+                              test = test_file_name,
+                              log = log,
+                              args = build.flags.args.join(" "));
+
+        let output = output(Command::new("adb").arg("shell").arg(&program));
+        println!("{}", output);
+        build.run(Command::new("adb")
+                          .arg("pull")
+                          .arg(&log)
+                          .arg(build.out.join("tmp")));
+        build.run(Command::new("adb").arg("shell").arg("rm").arg(&log));
+        if !output.contains("result: ok") {
+            panic!("some tests failed");
+        }
+    }
+}
+
+fn find_tests(dir: &Path,
+              target: &str,
+              dst: &mut Vec<PathBuf>) {
+    for e in t!(dir.read_dir()).map(|e| t!(e)) {
+        let file_type = t!(e.file_type());
+        if !file_type.is_file() {
+            continue
+        }
+        let filename = e.file_name().into_string().unwrap();
+        if (target.contains("windows") && filename.ends_with(".exe")) ||
+           (!target.contains("windows") && !filename.contains(".")) {
+            dst.push(e.path());
+        }
+    }
+}
+
+pub fn android_copy_libs(build: &Build,
+                         compiler: &Compiler,
+                         target: &str) {
+    println!("Android copy libs to emulator ({})", target);
+    build.run(Command::new("adb").arg("remount"));
+    build.run(Command::new("adb").args(&["shell", "rm", "-r", ADB_TEST_DIR]));
+    build.run(Command::new("adb").args(&["shell", "mkdir", ADB_TEST_DIR]));
+    build.run(Command::new("adb")
+                      .arg("push")
+                      .arg(build.src.join("src/etc/adb_run_wrapper.sh"))
+                      .arg(ADB_TEST_DIR));
+
+    let target_dir = format!("{}/{}", ADB_TEST_DIR, target);
+    build.run(Command::new("adb").args(&["shell", "mkdir", &target_dir[..]]));
+
+    for f in t!(build.sysroot_libdir(compiler, target).read_dir()) {
+        let f = t!(f);
+        let name = f.file_name().into_string().unwrap();
+        if util::is_dylib(&name) {
+            build.run(Command::new("adb")
+                              .arg("push")
+                              .arg(f.path())
+                              .arg(&target_dir));
+        }
+    }
 }
diff --git a/src/bootstrap/build/config.rs b/src/bootstrap/build/config.rs
index e155bf356a0..498196e9b6d 100644
--- a/src/bootstrap/build/config.rs
+++ b/src/bootstrap/build/config.rs
@@ -368,13 +368,13 @@ impl Config {
                     target.ndk = Some(PathBuf::from(value));
                 }
                 "CFG_I686_LINUX_ANDROID_NDK" if value.len() > 0 => {
-                    let target = "i686-linux-androideabi".to_string();
+                    let target = "i686-linux-android".to_string();
                     let target = self.target_config.entry(target)
                                      .or_insert(Target::default());
                     target.ndk = Some(PathBuf::from(value));
                 }
                 "CFG_AARCH64_LINUX_ANDROID_NDK" if value.len() > 0 => {
-                    let target = "aarch64-linux-androideabi".to_string();
+                    let target = "aarch64-linux-android".to_string();
                     let target = self.target_config.entry(target)
                                      .or_insert(Target::default());
                     target.ndk = Some(PathBuf::from(value));
diff --git a/src/bootstrap/build/dist.rs b/src/bootstrap/build/dist.rs
index 088e89b658d..6eed7eaf206 100644
--- a/src/bootstrap/build/dist.rs
+++ b/src/bootstrap/build/dist.rs
@@ -135,7 +135,6 @@ pub fn rustc(build: &Build, stage: u32, host: &str) {
 
     // Prepare the overlay which is part of the tarball but won't actually be
     // installed
-    t!(fs::create_dir_all(&overlay));
     let cp = |file: &str| {
         install(&build.src.join(file), &overlay, 0o644);
     };
@@ -199,7 +198,6 @@ pub fn rustc(build: &Build, stage: u32, host: &str) {
 
         // Copy runtime DLLs needed by the compiler
         if libdir != "bin" {
-            t!(fs::create_dir_all(image.join(libdir)));
             for entry in t!(src.join(libdir).read_dir()).map(|e| t!(e)) {
                 let name = entry.file_name();
                 if let Some(s) = name.to_str() {
@@ -221,7 +219,6 @@ pub fn rustc(build: &Build, stage: u32, host: &str) {
         let cp = |file: &str| {
             install(&build.src.join(file), &image.join("share/doc/rust"), 0o644);
         };
-        t!(fs::create_dir_all(&image.join("share/doc/rust")));
         cp("COPYRIGHT");
         cp("LICENSE-APACHE");
         cp("LICENSE-MIT");
@@ -289,6 +286,7 @@ pub fn std(build: &Build, compiler: &Compiler, target: &str) {
 
 fn install(src: &Path, dstdir: &Path, perms: u32) {
     let dst = dstdir.join(src.file_name().unwrap());
+    t!(fs::create_dir_all(dstdir));
     t!(fs::copy(src, &dst));
     chmod(&dst, perms);
 }
diff --git a/src/bootstrap/build/mod.rs b/src/bootstrap/build/mod.rs
index dadb0ffa6c9..195d1bc90c6 100644
--- a/src/bootstrap/build/mod.rs
+++ b/src/bootstrap/build/mod.rs
@@ -128,6 +128,7 @@ pub struct Build {
 ///
 /// These entries currently correspond to the various output directories of the
 /// build system, with each mod generating output in a different directory.
+#[derive(Clone, Copy)]
 pub enum Mode {
     /// This cargo is going to build the standard library, placing output in the
     /// "stageN-std" directory.
@@ -383,8 +384,7 @@ impl Build {
                                        "ui", "ui");
                 }
                 CheckDebuginfo { compiler } => {
-                    if target.target.contains("msvc") ||
-                       target.target.contains("android") {
+                    if target.target.contains("msvc") {
                         // nothing to do
                     } else if target.target.contains("apple") {
                         check::compiletest(self, &compiler, target.target,
@@ -434,8 +434,14 @@ impl Build {
                                            target.target);
                 }
 
+                AndroidCopyLibs { compiler } => {
+                    check::android_copy_libs(self, &compiler, target.target);
+                }
+
+                // pseudo-steps
                 Dist { .. } |
-                Doc { .. } | // pseudo-steps
+                Doc { .. } |
+                CheckTarget { .. } |
                 Check { .. } => {}
             }
         }
diff --git a/src/bootstrap/build/native.rs b/src/bootstrap/build/native.rs
index 557c9a4be54..f6030cfd090 100644
--- a/src/bootstrap/build/native.rs
+++ b/src/bootstrap/build/native.rs
@@ -49,6 +49,8 @@ pub fn llvm(build: &Build, target: &str) {
         return
     }
 
+    println!("Building LLVM for {}", target);
+
     let _ = fs::remove_dir_all(&dst.join("build"));
     t!(fs::create_dir_all(&dst.join("build")));
     let assertions = if build.config.llvm_assertions {"ON"} else {"OFF"};
@@ -167,8 +169,10 @@ pub fn compiler_rt(build: &Build, target: &str) {
             "arm" if target.contains("eabihf") => "armhf",
             _ => arch,
         };
-        let target = format!("clang_rt.builtins-{}{}", builtins_arch, os_extra);
-        ("linux".to_string(), target.clone(), target)
+        let target = format!("clang_rt.builtins-{}", builtins_arch);
+        ("linux".to_string(),
+         target.clone(),
+         format!("{}{}", target, os_extra))
     } else if target.contains("apple-darwin") {
         let builtins_arch = match arch {
             "i686" => "i386",
diff --git a/src/bootstrap/build/sanity.rs b/src/bootstrap/build/sanity.rs
index fd6cdc702cc..5eced00e139 100644
--- a/src/bootstrap/build/sanity.rs
+++ b/src/bootstrap/build/sanity.rs
@@ -139,6 +139,10 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake
 ");
             }
         }
+
+        if target.contains("arm-linux-android") {
+            need_cmd("adb".as_ref());
+        }
     }
 
     for host in build.flags.host.iter() {
diff --git a/src/bootstrap/build/step.rs b/src/bootstrap/build/step.rs
index 742fd8575bb..7cbbd6740a2 100644
--- a/src/bootstrap/build/step.rs
+++ b/src/bootstrap/build/step.rs
@@ -102,6 +102,7 @@ macro_rules! targets {
             // Steps for running tests. The 'check' target is just a pseudo
             // target to depend on a bunch of others.
             (check, Check { stage: u32, compiler: Compiler<'a> }),
+            (check_target, CheckTarget { stage: u32, compiler: Compiler<'a> }),
             (check_linkcheck, CheckLinkcheck { stage: u32 }),
             (check_cargotest, CheckCargoTest { stage: u32 }),
             (check_tidy, CheckTidy { stage: u32 }),
@@ -138,6 +139,9 @@ macro_rules! targets {
             (dist_mingw, DistMingw { _dummy: () }),
             (dist_rustc, DistRustc { stage: u32 }),
             (dist_std, DistStd { compiler: Compiler<'a> }),
+
+            // Misc targets
+            (android_copy_libs, AndroidCopyLibs { compiler: Compiler<'a> }),
         }
     }
 }
@@ -382,37 +386,80 @@ impl<'a> Step<'a> {
                      self.doc_error_index(stage)]
             }
             Source::Check { stage, compiler } => {
-                vec![
+                // Check is just a pseudo step which means check all targets,
+                // so just depend on checking all targets.
+                build.config.target.iter().map(|t| {
+                    self.target(t).check_target(stage, compiler)
+                }).collect()
+            }
+            Source::CheckTarget { stage, compiler } => {
+                // CheckTarget here means run all possible test suites for this
+                // target. Most of the time, however, we can't actually run
+                // anything if we're not the build triple as we could be cross
+                // compiling.
+                //
+                // As a result, the base set of targets here is quite stripped
+                // down from the standard set of targets. These suites have
+                // their own internal logic to run in cross-compiled situations
+                // if they'll run at all. For example compiletest knows that
+                // when testing Android targets we ship artifacts to the
+                // emulator.
+                //
+                // When in doubt the rule of thumb for adding to this list is
+                // "should this test suite run on the android bot?"
+                let mut base = vec![
                     self.check_rpass(compiler),
-                    self.check_rpass_full(compiler),
                     self.check_rfail(compiler),
-                    self.check_rfail_full(compiler),
-                    self.check_cfail(compiler),
-                    self.check_cfail_full(compiler),
-                    self.check_pfail(compiler),
-                    self.check_incremental(compiler),
-                    self.check_ui(compiler),
                     self.check_crate_std(compiler),
                     self.check_crate_test(compiler),
-                    self.check_crate_rustc(compiler),
-                    self.check_codegen(compiler),
-                    self.check_codegen_units(compiler),
                     self.check_debuginfo(compiler),
-                    self.check_rustdoc(compiler),
-                    self.check_pretty(compiler),
-                    self.check_pretty_rpass(compiler),
-                    self.check_pretty_rpass_full(compiler),
-                    self.check_pretty_rfail(compiler),
-                    self.check_pretty_rfail_full(compiler),
-                    self.check_pretty_rpass_valgrind(compiler),
-                    self.check_rpass_valgrind(compiler),
-                    self.check_error_index(compiler),
-                    self.check_docs(compiler),
-                    self.check_rmake(compiler),
-                    self.check_linkcheck(stage),
-                    self.check_tidy(stage),
                     self.dist(stage),
-                ]
+                ];
+
+                // If we're testing the build triple, then we know we can
+                // actually run binaries and such, so we run all possible tests
+                // that we know about.
+                if self.target == build.config.build {
+                    base.extend(vec![
+                        // docs-related
+                        self.check_docs(compiler),
+                        self.check_error_index(compiler),
+                        self.check_rustdoc(compiler),
+
+                        // UI-related
+                        self.check_cfail(compiler),
+                        self.check_pfail(compiler),
+                        self.check_ui(compiler),
+
+                        // codegen-related
+                        self.check_incremental(compiler),
+                        self.check_codegen(compiler),
+                        self.check_codegen_units(compiler),
+
+                        // misc compiletest-test suites
+                        self.check_rpass_full(compiler),
+                        self.check_rfail_full(compiler),
+                        self.check_cfail_full(compiler),
+                        self.check_pretty_rpass_full(compiler),
+                        self.check_pretty_rfail_full(compiler),
+                        self.check_rpass_valgrind(compiler),
+                        self.check_rmake(compiler),
+
+                        // crates
+                        self.check_crate_rustc(compiler),
+
+                        // pretty
+                        self.check_pretty(compiler),
+                        self.check_pretty_rpass(compiler),
+                        self.check_pretty_rfail(compiler),
+                        self.check_pretty_rpass_valgrind(compiler),
+
+                        // misc
+                        self.check_linkcheck(stage),
+                        self.check_tidy(stage),
+                    ]);
+                }
+                return base
             }
             Source::CheckLinkcheck { stage } => {
                 vec![self.tool_linkchecker(stage), self.doc(stage)]
@@ -437,16 +484,20 @@ impl<'a> Step<'a> {
             Source::CheckCFail { compiler } |
             Source::CheckRPassValgrind { compiler } |
             Source::CheckRPass { compiler } => {
-                vec![
+                let mut base = vec![
                     self.libtest(compiler),
-                    self.tool_compiletest(compiler.stage),
+                    self.target(compiler.host).tool_compiletest(compiler.stage),
                     self.test_helpers(()),
-                ]
+                ];
+                if self.target.contains("android") {
+                    base.push(self.android_copy_libs(compiler));
+                }
+                base
             }
             Source::CheckDebuginfo { compiler } => {
                 vec![
                     self.libtest(compiler),
-                    self.tool_compiletest(compiler.stage),
+                    self.target(compiler.host).tool_compiletest(compiler.stage),
                     self.test_helpers(()),
                     self.debugger_scripts(compiler.stage),
                 ]
@@ -459,13 +510,14 @@ impl<'a> Step<'a> {
             Source::CheckPrettyRPassValgrind { compiler } |
             Source::CheckRMake { compiler } => {
                 vec![self.librustc(compiler),
-                     self.tool_compiletest(compiler.stage)]
+                     self.target(compiler.host).tool_compiletest(compiler.stage)]
             }
             Source::CheckDocs { compiler } => {
                 vec![self.libstd(compiler)]
             }
             Source::CheckErrorIndex { compiler } => {
-                vec![self.libstd(compiler), self.tool_error_index(compiler.stage)]
+                vec![self.libstd(compiler),
+                     self.target(compiler.host).tool_error_index(compiler.stage)]
             }
             Source::CheckCrateStd { compiler } => {
                 vec![self.libtest(compiler)]
@@ -529,6 +581,10 @@ impl<'a> Step<'a> {
                 }
                 return base
             }
+
+            Source::AndroidCopyLibs { compiler } => {
+                vec![self.libtest(compiler)]
+            }
         }
     }
 }
diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in
index 1f3ea8f19bb..c657785d78b 100644
--- a/src/bootstrap/mk/Makefile.in
+++ b/src/bootstrap/mk/Makefile.in
@@ -25,6 +25,11 @@ all:
 clean:
 	$(Q)$(BOOTSTRAP) --clean
 
+rustc-stage1:
+	$(Q)$(BOOTSTRAP) --step libtest --stage 1
+rustc-stage2:
+	$(Q)$(BOOTSTRAP) --step libtest --stage 2
+
 docs: doc
 doc:
 	$(Q)$(BOOTSTRAP) --step doc
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index edb965c1962..94baf188bca 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -293,6 +293,12 @@ extern "rust-intrinsic" {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn transmute<T, U>(e: T) -> U;
 
+    /// Gives the address for the return value of the enclosing function.
+    ///
+    /// Using this intrinsic in a function that does not use an out pointer
+    /// will trigger a compiler error.
+    pub fn return_address() -> *const u8;
+
     /// Returns `true` if the actual type given as `T` requires drop
     /// glue; returns `false` if the actual type provided for `T`
     /// implements `Copy`.
diff --git a/src/librustc/dep_graph/thread.rs b/src/librustc/dep_graph/thread.rs
index 70d0a4e315c..4e16fae1870 100644
--- a/src/librustc/dep_graph/thread.rs
+++ b/src/librustc/dep_graph/thread.rs
@@ -118,8 +118,6 @@ impl DepGraphThreadData {
     /// the buffer is full, this may swap.)
     #[inline]
     pub fn enqueue(&self, message: DepMessage) {
-        debug!("enqueue: {:?} tasks_pushed={}", message, self.tasks_pushed.get());
-
         // Regardless of whether dep graph construction is enabled, we
         // still want to check that we always have a valid task on the
         // stack when a read/write/etc event occurs.
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index b6591471f0e..3b9ecb88258 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -908,6 +908,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 err.note("only the last field of a struct or enum variant \
                           may have a dynamically sized type");
             }
+            ObligationCauseCode::ConstSized => {
+                err.note("constant expressions must have a statically known size");
+            }
             ObligationCauseCode::SharedStatic => {
                 err.note("shared static variables must have a type that implements `Sync`");
             }
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index 68db5f86476..17aa6544fe7 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -127,6 +127,9 @@ pub enum ObligationCauseCode<'tcx> {
     // Types of fields (other than the last) in a struct must be sized.
     FieldSized,
 
+    // Constant expressions must be sized.
+    ConstSized,
+
     // static items must have `Sync` type
     SharedStatic,
 
diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs
index b3918f1e4bc..91234631499 100644
--- a/src/librustc_data_structures/indexed_vec.rs
+++ b/src/librustc_data_structures/indexed_vec.rs
@@ -15,6 +15,7 @@ use std::marker::PhantomData;
 use std::ops::{Index, IndexMut, Range};
 use std::fmt;
 use std::vec;
+use std::u32;
 
 use rustc_serialize as serialize;
 
@@ -31,6 +32,11 @@ impl Idx for usize {
     fn index(self) -> usize { self }
 }
 
+impl Idx for u32 {
+    fn new(idx: usize) -> Self { assert!(idx <= u32::MAX as usize); idx as u32 }
+    fn index(self) -> usize { self as usize }
+}
+
 #[derive(Clone)]
 pub struct IndexVec<I: Idx, T> {
     pub raw: Vec<T>,
diff --git a/src/librustc_data_structures/obligation_forest/mod.rs b/src/librustc_data_structures/obligation_forest/mod.rs
index b713b2285a6..c079146edbf 100644
--- a/src/librustc_data_structures/obligation_forest/mod.rs
+++ b/src/librustc_data_structures/obligation_forest/mod.rs
@@ -208,11 +208,17 @@ impl<O: ForestObligation> ObligationForest<O> {
     ///
     /// This CAN be done in a snapshot
     pub fn register_obligation(&mut self, obligation: O) {
-        self.register_obligation_at(obligation, None)
+        // Ignore errors here - there is no guarantee of success.
+        let _ = self.register_obligation_at(obligation, None);
     }
 
-    fn register_obligation_at(&mut self, obligation: O, parent: Option<NodeIndex>) {
-        if self.done_cache.contains(obligation.as_predicate()) { return }
+    // returns Err(()) if we already know this obligation failed.
+    fn register_obligation_at(&mut self, obligation: O, parent: Option<NodeIndex>)
+                              -> Result<(), ()>
+    {
+        if self.done_cache.contains(obligation.as_predicate()) {
+            return Ok(())
+        }
 
         match self.waiting_cache.entry(obligation.as_predicate().clone()) {
             Entry::Occupied(o) => {
@@ -226,6 +232,11 @@ impl<O: ForestObligation> ObligationForest<O> {
                         self.nodes[o.get().get()].dependents.push(parent);
                     }
                 }
+                if let NodeState::Error = self.nodes[o.get().get()].state.get() {
+                    Err(())
+                } else {
+                    Ok(())
+                }
             }
             Entry::Vacant(v) => {
                 debug!("register_obligation_at({:?}, {:?}) - ok",
@@ -233,8 +244,9 @@ impl<O: ForestObligation> ObligationForest<O> {
                 v.insert(NodeIndex::new(self.nodes.len()));
                 self.cache_list.push(obligation.as_predicate().clone());
                 self.nodes.push(Node::new(parent, obligation));
+                Ok(())
             }
-        };
+        }
     }
 
     /// Convert all remaining obligations to the given error.
@@ -306,12 +318,19 @@ impl<O: ForestObligation> ObligationForest<O> {
                 Ok(Some(children)) => {
                     // if we saw a Some(_) result, we are not (yet) stalled
                     stalled = false;
+                    self.nodes[index].state.set(NodeState::Success);
+
                     for child in children {
-                        self.register_obligation_at(child,
-                                                    Some(NodeIndex::new(index)));
+                        let st = self.register_obligation_at(
+                            child,
+                            Some(NodeIndex::new(index))
+                        );
+                        if let Err(()) = st {
+                            // error already reported - propagate it
+                            // to our node.
+                            self.error_at(index);
+                        }
                     }
-
-                    self.nodes[index].state.set(NodeState::Success);
                 }
                 Err(err) => {
                     let backtrace = self.error_at(index);
diff --git a/src/librustc_data_structures/obligation_forest/test.rs b/src/librustc_data_structures/obligation_forest/test.rs
index 8eac8892a3e..a95b2b84b34 100644
--- a/src/librustc_data_structures/obligation_forest/test.rs
+++ b/src/librustc_data_structures/obligation_forest/test.rs
@@ -418,3 +418,43 @@ fn orphan() {
     let errors = forest.to_errors(());
     assert_eq!(errors.len(), 0);
 }
+
+#[test]
+fn simultaneous_register_and_error() {
+    // check that registering a failed obligation works correctly
+    let mut forest = ObligationForest::new();
+    forest.register_obligation("A");
+    forest.register_obligation("B");
+
+    let Outcome { completed: ok, errors: err, .. } =
+        forest.process_obligations(&mut C(|obligation| {
+            match *obligation {
+                "A" => Err("An error"),
+                "B" => Ok(Some(vec!["A"])),
+                _ => unreachable!(),
+            }
+        }, |_|{}));
+    assert_eq!(ok.len(), 0);
+    assert_eq!(err, vec![super::Error {
+        error: "An error",
+        backtrace: vec!["A"]
+    }]);
+
+    let mut forest = ObligationForest::new();
+    forest.register_obligation("B");
+    forest.register_obligation("A");
+
+    let Outcome { completed: ok, errors: err, .. } =
+        forest.process_obligations(&mut C(|obligation| {
+            match *obligation {
+                "A" => Err("An error"),
+                "B" => Ok(Some(vec!["A"])),
+                _ => unreachable!(),
+            }
+        }, |_|{}));
+    assert_eq!(ok.len(), 0);
+    assert_eq!(err, vec![super::Error {
+        error: "An error",
+        backtrace: vec!["A"]
+    }]);
+}
diff --git a/src/librustc_metadata/Cargo.toml b/src/librustc_metadata/Cargo.toml
index 11896e17630..2d3302c2eef 100644
--- a/src/librustc_metadata/Cargo.toml
+++ b/src/librustc_metadata/Cargo.toml
@@ -16,6 +16,7 @@ rustc = { path = "../librustc" }
 rustc_back = { path = "../librustc_back" }
 rustc_bitflags = { path = "../librustc_bitflags" }
 rustc_const_math = { path = "../librustc_const_math" }
+rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
 rustc_llvm = { path = "../librustc_llvm" }
 serialize = { path = "../libserialize" }
diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs
index 7ef00b971c5..2e8c5a7c234 100644
--- a/src/librustc_metadata/astencode.rs
+++ b/src/librustc_metadata/astencode.rs
@@ -60,7 +60,7 @@ use rustc_serialize::{Encodable, EncoderHelpers};
 
 struct DecodeContext<'a, 'b, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    cdata: &'b cstore::crate_metadata,
+    cdata: &'b cstore::CrateMetadata,
     from_id_range: IdRange,
     to_id_range: IdRange,
     // Cache the last used filemap for translating spans as an optimization.
@@ -121,7 +121,7 @@ impl<'a, 'b, 'c, 'tcx> ast_map::FoldOps for &'a DecodeContext<'b, 'c, 'tcx> {
 
 /// Decodes an item from its AST in the cdata's metadata and adds it to the
 /// ast-map.
-pub fn decode_inlined_item<'a, 'tcx>(cdata: &cstore::crate_metadata,
+pub fn decode_inlined_item<'a, 'tcx>(cdata: &cstore::CrateMetadata,
                                      tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                      parent_def_path: ast_map::DefPath,
                                      parent_did: DefId,
@@ -246,7 +246,7 @@ impl<S:serialize::Encoder> def_id_encoder_helpers for S
 trait def_id_decoder_helpers {
     fn read_def_id(&mut self, dcx: &DecodeContext) -> DefId;
     fn read_def_id_nodcx(&mut self,
-                         cdata: &cstore::crate_metadata) -> DefId;
+                         cdata: &cstore::CrateMetadata) -> DefId;
 }
 
 impl<D:serialize::Decoder> def_id_decoder_helpers for D
@@ -258,7 +258,7 @@ impl<D:serialize::Decoder> def_id_decoder_helpers for D
     }
 
     fn read_def_id_nodcx(&mut self,
-                         cdata: &cstore::crate_metadata)
+                         cdata: &cstore::CrateMetadata)
                          -> DefId {
         let did: DefId = Decodable::decode(self).unwrap();
         decoder::translate_def_id(cdata, did)
@@ -858,17 +858,17 @@ trait rbml_decoder_decoder_helpers<'tcx> {
     // Versions of the type reading functions that don't need the full
     // DecodeContext.
     fn read_ty_nodcx<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                         cdata: &cstore::crate_metadata) -> Ty<'tcx>;
+                         cdata: &cstore::CrateMetadata) -> Ty<'tcx>;
     fn read_tys_nodcx<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                          cdata: &cstore::crate_metadata) -> Vec<Ty<'tcx>>;
+                          cdata: &cstore::CrateMetadata) -> Vec<Ty<'tcx>>;
     fn read_substs_nodcx<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                             cdata: &cstore::crate_metadata)
+                             cdata: &cstore::CrateMetadata)
                              -> subst::Substs<'tcx>;
 }
 
 impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
     fn read_ty_nodcx<'b>(&mut self, tcx: TyCtxt<'b, 'tcx, 'tcx>,
-                         cdata: &cstore::crate_metadata)
+                         cdata: &cstore::CrateMetadata)
                          -> Ty<'tcx> {
         self.read_opaque(|_, doc| {
             Ok(
@@ -879,7 +879,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
     }
 
     fn read_tys_nodcx<'b>(&mut self, tcx: TyCtxt<'b, 'tcx, 'tcx>,
-                          cdata: &cstore::crate_metadata) -> Vec<Ty<'tcx>> {
+                          cdata: &cstore::CrateMetadata) -> Vec<Ty<'tcx>> {
         self.read_to_vec(|this| Ok(this.read_ty_nodcx(tcx, cdata)) )
             .unwrap()
             .into_iter()
@@ -887,7 +887,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
     }
 
     fn read_substs_nodcx<'b>(&mut self, tcx: TyCtxt<'b, 'tcx, 'tcx>,
-                             cdata: &cstore::crate_metadata)
+                             cdata: &cstore::CrateMetadata)
                              -> subst::Substs<'tcx>
     {
         self.read_opaque(|_, doc| {
diff --git a/src/librustc_metadata/common.rs b/src/librustc_metadata/common.rs
index 74f97de2658..ff072cce5db 100644
--- a/src/librustc_metadata/common.rs
+++ b/src/librustc_metadata/common.rs
@@ -252,3 +252,7 @@ pub fn rustc_version() -> String {
 }
 
 pub const tag_panic_strategy: usize = 0x114;
+
+// NB: increment this if you change the format of metadata such that
+// rustc_version can't be found.
+pub const metadata_encoding_version : &'static [u8] = &[b'r', b'u', b's', b't', 0, 0, 0, 2];
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index 2ccac91ae91..269e284b22d 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -12,7 +12,6 @@
 
 //! Validates all used crates and extern libraries and loads their metadata
 
-use common::rustc_version;
 use cstore::{self, CStore, CrateSource, MetadataBlob};
 use decoder;
 use loader::{self, CratePaths};
@@ -24,7 +23,7 @@ use rustc::session::{config, Session};
 use rustc::session::config::PanicStrategy;
 use rustc::session::search_paths::PathKind;
 use rustc::middle::cstore::{CrateStore, validate_crate_name, ExternCrate};
-use rustc::util::nodemap::FnvHashMap;
+use rustc::util::nodemap::{FnvHashMap, FnvHashSet};
 use rustc::hir::map as hir_map;
 
 use std::cell::{RefCell, Cell};
@@ -132,7 +131,7 @@ struct ExtensionCrate {
 }
 
 enum PMDSource {
-    Registered(Rc<cstore::crate_metadata>),
+    Registered(Rc<cstore::CrateMetadata>),
     Owned(MetadataBlob),
 }
 
@@ -236,25 +235,6 @@ impl<'a> CrateReader<'a> {
         return ret;
     }
 
-    fn verify_rustc_version(&self,
-                            name: &str,
-                            span: Span,
-                            metadata: &MetadataBlob) {
-        let crate_rustc_version = decoder::crate_rustc_version(metadata.as_slice());
-        if crate_rustc_version != Some(rustc_version()) {
-            let mut err = struct_span_fatal!(self.sess, span, E0514,
-                                             "the crate `{}` has been compiled with {}, which is \
-                                              incompatible with this version of rustc",
-                                              name,
-                                              crate_rustc_version
-                                              .as_ref().map(|s| &**s)
-                                              .unwrap_or("an old version of rustc"));
-            err.help("consider removing the compiled binaries and recompiling \
-                      with your current version of rustc");
-            err.emit();
-        }
-    }
-
     fn verify_no_symbol_conflicts(&self,
                                   span: Span,
                                   metadata: &MetadataBlob) {
@@ -294,9 +274,8 @@ impl<'a> CrateReader<'a> {
                       span: Span,
                       lib: loader::Library,
                       explicitly_linked: bool)
-                      -> (ast::CrateNum, Rc<cstore::crate_metadata>,
+                      -> (ast::CrateNum, Rc<cstore::CrateMetadata>,
                           cstore::CrateSource) {
-        self.verify_rustc_version(name, span, &lib.metadata);
         self.verify_no_symbol_conflicts(span, &lib.metadata);
 
         // Claim this crate number and cache it
@@ -318,10 +297,10 @@ impl<'a> CrateReader<'a> {
 
         let loader::Library { dylib, rlib, metadata } = lib;
 
-        let cnum_map = self.resolve_crate_deps(root, metadata.as_slice(), span);
+        let cnum_map = self.resolve_crate_deps(root, metadata.as_slice(), cnum, span);
         let staged_api = self.is_staged_api(metadata.as_slice());
 
-        let cmeta = Rc::new(cstore::crate_metadata {
+        let cmeta = Rc::new(cstore::CrateMetadata {
             name: name.to_string(),
             extern_crate: Cell::new(None),
             index: decoder::load_index(metadata.as_slice()),
@@ -364,7 +343,7 @@ impl<'a> CrateReader<'a> {
                      span: Span,
                      kind: PathKind,
                      explicitly_linked: bool)
-                     -> (ast::CrateNum, Rc<cstore::crate_metadata>, cstore::CrateSource) {
+                     -> (ast::CrateNum, Rc<cstore::CrateMetadata>, cstore::CrateSource) {
         let result = match self.existing_match(name, hash, kind) {
             Some(cnum) => LoadResult::Previous(cnum),
             None => {
@@ -381,6 +360,7 @@ impl<'a> CrateReader<'a> {
                     rejected_via_hash: vec!(),
                     rejected_via_triple: vec!(),
                     rejected_via_kind: vec!(),
+                    rejected_via_version: vec!(),
                     should_match_name: true,
                 };
                 match self.load(&mut load_ctxt) {
@@ -438,8 +418,11 @@ impl<'a> CrateReader<'a> {
 
     fn update_extern_crate(&mut self,
                            cnum: ast::CrateNum,
-                           mut extern_crate: ExternCrate)
+                           mut extern_crate: ExternCrate,
+                           visited: &mut FnvHashSet<(ast::CrateNum, bool)>)
     {
+        if !visited.insert((cnum, extern_crate.direct)) { return }
+
         let cmeta = self.cstore.get_crate_data(cnum);
         let old_extern_crate = cmeta.extern_crate.get();
 
@@ -458,11 +441,10 @@ impl<'a> CrateReader<'a> {
         }
 
         cmeta.extern_crate.set(Some(extern_crate));
-
         // Propagate the extern crate info to dependencies.
         extern_crate.direct = false;
-        for &dep_cnum in cmeta.cnum_map.borrow().values() {
-            self.update_extern_crate(dep_cnum, extern_crate);
+        for &dep_cnum in cmeta.cnum_map.borrow().iter() {
+            self.update_extern_crate(dep_cnum, extern_crate, visited);
         }
     }
 
@@ -470,12 +452,13 @@ impl<'a> CrateReader<'a> {
     fn resolve_crate_deps(&mut self,
                           root: &Option<CratePaths>,
                           cdata: &[u8],
-                          span : Span)
-                          -> cstore::cnum_map {
+                          krate: ast::CrateNum,
+                          span: Span)
+                          -> cstore::CrateNumMap {
         debug!("resolving deps of external crate");
         // The map from crate numbers in the crate we're resolving to local crate
         // numbers
-        decoder::get_crate_deps(cdata).iter().map(|dep| {
+        let map: FnvHashMap<_, _> = decoder::get_crate_deps(cdata).iter().map(|dep| {
             debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash);
             let (local_cnum, _, _) = self.resolve_crate(root,
                                                         &dep.name,
@@ -485,7 +468,13 @@ impl<'a> CrateReader<'a> {
                                                         PathKind::Dependency,
                                                         dep.explicitly_linked);
             (dep.cnum, local_cnum)
-        }).collect()
+        }).collect();
+
+        let max_cnum = map.values().cloned().max().unwrap_or(0);
+
+        // we map 0 and all other holes in the map to our parent crate. The "additional"
+        // self-dependencies should be harmless.
+        (0..max_cnum+1).map(|cnum| map.get(&cnum).cloned().unwrap_or(krate)).collect()
     }
 
     fn read_extension_crate(&mut self, span: Span, info: &CrateInfo) -> ExtensionCrate {
@@ -508,6 +497,7 @@ impl<'a> CrateReader<'a> {
             rejected_via_hash: vec!(),
             rejected_via_triple: vec!(),
             rejected_via_kind: vec!(),
+            rejected_via_version: vec!(),
             should_match_name: true,
         };
         let library = self.load(&mut load_ctxt).or_else(|| {
@@ -826,7 +816,7 @@ impl<'a> CrateReader<'a> {
     fn inject_dependency_if(&self,
                             krate: ast::CrateNum,
                             what: &str,
-                            needs_dep: &Fn(&cstore::crate_metadata) -> bool) {
+                            needs_dep: &Fn(&cstore::CrateMetadata) -> bool) {
         // don't perform this validation if the session has errors, as one of
         // those errors may indicate a circular dependency which could cause
         // this to stack overflow.
@@ -837,7 +827,17 @@ impl<'a> CrateReader<'a> {
         // Before we inject any dependencies, make sure we don't inject a
         // circular dependency by validating that this crate doesn't
         // transitively depend on any crates satisfying `needs_dep`.
-        validate(self, krate, krate, what, needs_dep);
+        for dep in self.cstore.crate_dependencies_in_rpo(krate) {
+            let data = self.cstore.get_crate_data(dep);
+            if needs_dep(&data) {
+                self.sess.err(&format!("the crate `{}` cannot depend \
+                                        on a crate that needs {}, but \
+                                        it depends on `{}`",
+                                       self.cstore.get_crate_data(krate).name(),
+                                       what,
+                                       data.name()));
+            }
+        }
 
         // All crates satisfying `needs_dep` do not explicitly depend on the
         // crate provided for this compile, but in order for this compilation to
@@ -849,32 +849,8 @@ impl<'a> CrateReader<'a> {
             }
 
             info!("injecting a dep from {} to {}", cnum, krate);
-            let mut cnum_map = data.cnum_map.borrow_mut();
-            let remote_cnum = cnum_map.len() + 1;
-            let prev = cnum_map.insert(remote_cnum as ast::CrateNum, krate);
-            assert!(prev.is_none());
+            data.cnum_map.borrow_mut().push(krate);
         });
-
-        fn validate(me: &CrateReader,
-                    krate: ast::CrateNum,
-                    root: ast::CrateNum,
-                    what: &str,
-                    needs_dep: &Fn(&cstore::crate_metadata) -> bool) {
-            let data = me.cstore.get_crate_data(krate);
-            if needs_dep(&data) {
-                let krate_name = data.name();
-                let data = me.cstore.get_crate_data(root);
-                let root_name = data.name();
-                me.sess.err(&format!("the crate `{}` cannot depend \
-                                      on a crate that needs {}, but \
-                                      it depends on `{}`", root_name, what,
-                                      krate_name));
-            }
-
-            for (_, &dep) in data.cnum_map.borrow().iter() {
-                validate(me, dep, root, what, needs_dep);
-            }
-        }
     }
 }
 
@@ -948,7 +924,8 @@ impl<'a> LocalCrateReader<'a> {
                                                          span: i.span,
                                                          direct: true,
                                                          path_len: len,
-                                                     });
+                                                     },
+                                                     &mut FnvHashSet());
                     self.cstore.add_extern_mod_stmt_cnum(info.id, cnum);
                 }
             }
diff --git a/src/librustc_metadata/csearch.rs b/src/librustc_metadata/csearch.rs
index 3134a3844bc..95e3c53ecb4 100644
--- a/src/librustc_metadata/csearch.rs
+++ b/src/librustc_metadata/csearch.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use cstore;
+use common;
 use decoder;
 use encoder;
 use loader;
@@ -588,7 +589,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
 
     fn metadata_encoding_version(&self) -> &[u8]
     {
-        encoder::metadata_encoding_version
+        common::metadata_encoding_version
     }
 
     /// Returns a map from a sufficiently visible external item (i.e. an external item that is
diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs
index e89f428c96f..774d0f7ea18 100644
--- a/src/librustc_metadata/cstore.rs
+++ b/src/librustc_metadata/cstore.rs
@@ -15,6 +15,7 @@
 
 pub use self::MetadataBlob::*;
 
+use common;
 use creader;
 use decoder;
 use index;
@@ -26,6 +27,7 @@ use rustc::hir::map::DefKey;
 use rustc::hir::svh::Svh;
 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};
 
 use std::cell::{RefCell, Ref, Cell};
@@ -46,7 +48,7 @@ pub use middle::cstore::{CrateSource, LinkMeta};
 // local crate numbers (as generated during this session). Each external
 // crate may refer to types in other external crates, and each has their
 // own crate numbers.
-pub type cnum_map = FnvHashMap<ast::CrateNum, ast::CrateNum>;
+pub type CrateNumMap = IndexVec<ast::CrateNum, ast::CrateNum>;
 
 pub enum MetadataBlob {
     MetadataVec(Bytes),
@@ -64,7 +66,7 @@ pub struct ImportedFileMap {
     pub translated_filemap: Rc<syntax_pos::FileMap>
 }
 
-pub struct crate_metadata {
+pub struct CrateMetadata {
     pub name: String,
 
     /// Information about the extern crate that caused this crate to
@@ -73,7 +75,7 @@ pub struct crate_metadata {
     pub extern_crate: Cell<Option<ExternCrate>>,
 
     pub data: MetadataBlob,
-    pub cnum_map: RefCell<cnum_map>,
+    pub cnum_map: RefCell<CrateNumMap>,
     pub cnum: ast::CrateNum,
     pub codemap_import_info: RefCell<Vec<ImportedFileMap>>,
     pub staged_api: bool,
@@ -97,7 +99,7 @@ pub struct crate_metadata {
 
 pub struct CStore {
     pub dep_graph: DepGraph,
-    metas: RefCell<FnvHashMap<ast::CrateNum, Rc<crate_metadata>>>,
+    metas: RefCell<FnvHashMap<ast::CrateNum, Rc<CrateMetadata>>>,
     /// Map from NodeId's of local extern crate statements to crate numbers
     extern_mod_crate_map: RefCell<NodeMap<ast::CrateNum>>,
     used_crate_sources: RefCell<Vec<CrateSource>>,
@@ -128,7 +130,7 @@ impl CStore {
         self.metas.borrow().len() as ast::CrateNum + 1
     }
 
-    pub fn get_crate_data(&self, cnum: ast::CrateNum) -> Rc<crate_metadata> {
+    pub fn get_crate_data(&self, cnum: ast::CrateNum) -> Rc<CrateMetadata> {
         self.metas.borrow().get(&cnum).unwrap().clone()
     }
 
@@ -137,12 +139,12 @@ impl CStore {
         decoder::get_crate_hash(cdata.data())
     }
 
-    pub fn set_crate_data(&self, cnum: ast::CrateNum, data: Rc<crate_metadata>) {
+    pub fn set_crate_data(&self, cnum: ast::CrateNum, data: Rc<CrateMetadata>) {
         self.metas.borrow_mut().insert(cnum, data);
     }
 
     pub fn iter_crate_data<I>(&self, mut i: I) where
-        I: FnMut(ast::CrateNum, &Rc<crate_metadata>),
+        I: FnMut(ast::CrateNum, &Rc<CrateMetadata>),
     {
         for (&k, v) in self.metas.borrow().iter() {
             i(k, v);
@@ -151,7 +153,7 @@ impl CStore {
 
     /// Like `iter_crate_data`, but passes source paths (if available) as well.
     pub fn iter_crate_data_origins<I>(&self, mut i: I) where
-        I: FnMut(ast::CrateNum, &crate_metadata, Option<CrateSource>),
+        I: FnMut(ast::CrateNum, &CrateMetadata, Option<CrateSource>),
     {
         for (&k, v) in self.metas.borrow().iter() {
             let origin = self.opt_used_crate_source(k);
@@ -182,6 +184,30 @@ impl CStore {
         self.statically_included_foreign_items.borrow_mut().clear();
     }
 
+    pub fn crate_dependencies_in_rpo(&self, krate: ast::CrateNum) -> Vec<ast::CrateNum>
+    {
+        let mut ordering = Vec::new();
+        self.push_dependencies_in_postorder(&mut ordering, krate);
+        ordering.reverse();
+        ordering
+    }
+
+    pub fn push_dependencies_in_postorder(&self,
+                                          ordering: &mut Vec<ast::CrateNum>,
+                                          krate: ast::CrateNum)
+    {
+        if ordering.contains(&krate) { return }
+
+        let data = self.get_crate_data(krate);
+        for &dep in data.cnum_map.borrow().iter() {
+            if dep != krate {
+                self.push_dependencies_in_postorder(ordering, dep);
+            }
+        }
+
+        ordering.push(krate);
+    }
+
     // This method is used when generating the command line to pass through to
     // system linker. The linker expects undefined symbols on the left of the
     // command line to be defined in libraries on the right, not the other way
@@ -194,17 +220,8 @@ impl CStore {
     pub fn do_get_used_crates(&self, prefer: LinkagePreference)
                               -> Vec<(ast::CrateNum, Option<PathBuf>)> {
         let mut ordering = Vec::new();
-        fn visit(cstore: &CStore, cnum: ast::CrateNum,
-                 ordering: &mut Vec<ast::CrateNum>) {
-            if ordering.contains(&cnum) { return }
-            let meta = cstore.get_crate_data(cnum);
-            for (_, &dep) in meta.cnum_map.borrow().iter() {
-                visit(cstore, dep, ordering);
-            }
-            ordering.push(cnum);
-        }
         for (&num, _) in self.metas.borrow().iter() {
-            visit(self, num, &mut ordering);
+            self.push_dependencies_in_postorder(&mut ordering, num);
         }
         info!("topological ordering: {:?}", ordering);
         ordering.reverse();
@@ -264,7 +281,7 @@ impl CStore {
     }
 }
 
-impl crate_metadata {
+impl CrateMetadata {
     pub fn data<'a>(&'a self) -> &'a [u8] { self.data.as_slice() }
     pub fn name(&self) -> &str { decoder::get_crate_name(self.data()) }
     pub fn hash(&self) -> Svh { decoder::get_crate_hash(self.data()) }
@@ -312,20 +329,25 @@ impl crate_metadata {
 }
 
 impl MetadataBlob {
-    pub fn as_slice<'a>(&'a self) -> &'a [u8] {
-        let slice = match *self {
+    pub fn as_slice_raw<'a>(&'a self) -> &'a [u8] {
+        match *self {
             MetadataVec(ref vec) => &vec[..],
             MetadataArchive(ref ar) => ar.as_slice(),
-        };
-        if slice.len() < 4 {
+        }
+    }
+
+    pub fn as_slice<'a>(&'a self) -> &'a [u8] {
+        let slice = self.as_slice_raw();
+        let len_offset = 4 + common::metadata_encoding_version.len();
+        if slice.len() < len_offset+4 {
             &[] // corrupt metadata
         } else {
-            let len = (((slice[0] as u32) << 24) |
-                       ((slice[1] as u32) << 16) |
-                       ((slice[2] as u32) << 8) |
-                       ((slice[3] as u32) << 0)) as usize;
-            if len + 4 <= slice.len() {
-                &slice[4.. len + 4]
+            let len = (((slice[len_offset+0] as u32) << 24) |
+                       ((slice[len_offset+1] as u32) << 16) |
+                       ((slice[len_offset+2] as u32) << 8) |
+                       ((slice[len_offset+3] as u32) << 0)) as usize;
+            if len <= slice.len() - 4 - len_offset {
+                &slice[len_offset + 4..len_offset + len + 4]
             } else {
                 &[] // corrupt or old metadata
             }
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 3efdf36acd9..0a59c152ca3 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -15,7 +15,7 @@
 use self::Family::*;
 
 use astencode::decode_inlined_item;
-use cstore::{self, crate_metadata};
+use cstore::{self, CrateMetadata};
 use common::*;
 use def_key;
 use encoder::def_to_u64;
@@ -30,7 +30,7 @@ use rustc::util::nodemap::FnvHashMap;
 use rustc::hir;
 use rustc::session::config::PanicStrategy;
 
-use middle::cstore::{LOCAL_CRATE, FoundAst, InlinedItem, LinkagePreference};
+use middle::cstore::{FoundAst, InlinedItem, LinkagePreference};
 use middle::cstore::{DefLike, DlDef, DlField, DlImpl, tls};
 use rustc::hir::def::Def;
 use rustc::hir::def_id::{DefId, DefIndex};
@@ -61,9 +61,9 @@ use syntax::print::pprust;
 use syntax::ptr::P;
 use syntax_pos::{self, Span, BytePos, NO_EXPANSION};
 
-pub type Cmd<'a> = &'a crate_metadata;
+pub type Cmd<'a> = &'a CrateMetadata;
 
-impl crate_metadata {
+impl CrateMetadata {
     fn get_item(&self, item_id: DefIndex) -> Option<rbml::Doc> {
         self.index.lookup_item(self.data(), item_id).map(|pos| {
             reader::doc_at(self.data(), pos as usize).unwrap().doc
@@ -663,7 +663,7 @@ fn each_child_of_item_or_crate<F, G>(intr: Rc<IdentInterner>,
                                      mut get_crate_data: G,
                                      mut callback: F) where
     F: FnMut(DefLike, ast::Name, ty::Visibility),
-    G: FnMut(ast::CrateNum) -> Rc<crate_metadata>,
+    G: FnMut(ast::CrateNum) -> Rc<CrateMetadata>,
 {
     // Iterate over all children.
     for child_info_doc in reader::tagged_docs(item_doc, tag_mod_child) {
@@ -758,7 +758,7 @@ pub fn each_child_of_item<F, G>(intr: Rc<IdentInterner>,
                                get_crate_data: G,
                                callback: F) where
     F: FnMut(DefLike, ast::Name, ty::Visibility),
-    G: FnMut(ast::CrateNum) -> Rc<crate_metadata>,
+    G: FnMut(ast::CrateNum) -> Rc<CrateMetadata>,
 {
     // Find the item.
     let item_doc = match cdata.get_item(id) {
@@ -779,7 +779,7 @@ pub fn each_top_level_item_of_crate<F, G>(intr: Rc<IdentInterner>,
                                           get_crate_data: G,
                                           callback: F) where
     F: FnMut(DefLike, ast::Name, ty::Visibility),
-    G: FnMut(ast::CrateNum) -> Rc<crate_metadata>,
+    G: FnMut(ast::CrateNum) -> Rc<CrateMetadata>,
 {
     let root_doc = rbml::Doc::new(cdata.data());
     let misc_info_doc = reader::get_doc(root_doc, tag_misc_info);
@@ -1348,25 +1348,16 @@ pub fn translate_def_id(cdata: Cmd, did: DefId) -> DefId {
         return DefId { krate: cdata.cnum, index: did.index };
     }
 
-    match cdata.cnum_map.borrow().get(&did.krate) {
-        Some(&n) => {
-            DefId {
-                krate: n,
-                index: did.index,
-            }
-        }
-        None => bug!("didn't find a crate in the cnum_map")
+    DefId {
+        krate: cdata.cnum_map.borrow()[did.krate],
+        index: did.index
     }
 }
 
 // Translate a DefId from the current compilation environment to a DefId
 // for an external crate.
 fn reverse_translate_def_id(cdata: Cmd, did: DefId) -> Option<DefId> {
-    if did.krate == cdata.cnum {
-        return Some(DefId { krate: LOCAL_CRATE, index: did.index });
-    }
-
-    for (&local, &global) in cdata.cnum_map.borrow().iter() {
+    for (local, &global) in cdata.cnum_map.borrow().iter_enumerated() {
         if global == did.krate {
             return Some(DefId { krate: local, index: did.index });
         }
@@ -1545,10 +1536,7 @@ pub fn get_dylib_dependency_formats(cdata: Cmd)
         let cnum = spec.split(':').nth(0).unwrap();
         let link = spec.split(':').nth(1).unwrap();
         let cnum: ast::CrateNum = cnum.parse().unwrap();
-        let cnum = match cdata.cnum_map.borrow().get(&cnum) {
-            Some(&n) => n,
-            None => bug!("didn't find a crate in the cnum_map")
-        };
+        let cnum = cdata.cnum_map.borrow()[cnum];
         result.push((cnum, if link == "d" {
             LinkagePreference::RequireDynamic
         } else {
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index c23ad6d5f07..b6f49569958 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -1351,6 +1351,7 @@ fn my_visit_expr(expr: &hir::Expr,
 
             rbml_w.start_tag(tag_items_data_item);
             encode_def_id_and_key(ecx, rbml_w, def_id);
+            encode_name(rbml_w, syntax::parse::token::intern("<closure>"));
 
             rbml_w.start_tag(tag_items_closure_ty);
             write_closure_type(ecx, rbml_w, &ecx.tcx.tables.borrow().closure_tys[&def_id]);
@@ -1505,7 +1506,7 @@ fn encode_polarity(rbml_w: &mut Encoder, polarity: hir::ImplPolarity) {
 
 fn encode_crate_deps(rbml_w: &mut Encoder, cstore: &cstore::CStore) {
     fn get_ordered_deps(cstore: &cstore::CStore)
-                        -> Vec<(CrateNum, Rc<cstore::crate_metadata>)> {
+                        -> Vec<(CrateNum, Rc<cstore::CrateMetadata>)> {
         // Pull the cnums and name,vers,hash out of cstore
         let mut deps = Vec::new();
         cstore.iter_crate_data(|cnum, val| {
@@ -1736,7 +1737,7 @@ fn encode_reachable(ecx: &EncodeContext, rbml_w: &mut Encoder) {
 }
 
 fn encode_crate_dep(rbml_w: &mut Encoder,
-                    dep: &cstore::crate_metadata) {
+                    dep: &cstore::CrateMetadata) {
     rbml_w.start_tag(tag_crate_dep);
     rbml_w.wr_tagged_str(tag_crate_dep_crate_name, &dep.name());
     let hash = decoder::get_crate_hash(dep.data());
@@ -1798,10 +1799,6 @@ fn encode_panic_strategy(rbml_w: &mut Encoder, ecx: &EncodeContext) {
     }
 }
 
-// NB: Increment this as you change the metadata encoding version.
-#[allow(non_upper_case_globals)]
-pub const metadata_encoding_version : &'static [u8] = &[b'r', b'u', b's', b't', 0, 0, 0, 2 ];
-
 pub fn encode_metadata(ecx: EncodeContext, krate: &hir::Crate) -> Vec<u8> {
     let mut wr = Cursor::new(Vec::new());
 
@@ -1835,12 +1832,25 @@ pub fn encode_metadata(ecx: EncodeContext, krate: &hir::Crate) -> Vec<u8> {
     // the length of the metadata to the start of the metadata. Later on this
     // will allow us to slice the metadata to the precise length that we just
     // generated regardless of trailing bytes that end up in it.
-    let len = v.len() as u32;
-    v.insert(0, (len >>  0) as u8);
-    v.insert(0, (len >>  8) as u8);
-    v.insert(0, (len >> 16) as u8);
-    v.insert(0, (len >> 24) as u8);
-    return v;
+    //
+    // We also need to store the metadata encoding version here, because
+    // rlibs don't have it. To get older versions of rustc to ignore
+    // this metadata, there are 4 zero bytes at the start, which are
+    // treated as a length of 0 by old compilers.
+
+    let len = v.len();
+    let mut result = vec![];
+    result.push(0);
+    result.push(0);
+    result.push(0);
+    result.push(0);
+    result.extend(metadata_encoding_version.iter().cloned());
+    result.push((len >> 24) as u8);
+    result.push((len >> 16) as u8);
+    result.push((len >>  8) as u8);
+    result.push((len >>  0) as u8);
+    result.extend(v);
+    result
 }
 
 fn encode_metadata_inner(rbml_w: &mut Encoder,
diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs
index 1cf7282e9e9..cd92493e3db 100644
--- a/src/librustc_metadata/lib.rs
+++ b/src/librustc_metadata/lib.rs
@@ -36,6 +36,7 @@ extern crate rustc_errors as errors;
 
 #[macro_use]
 extern crate rustc;
+extern crate rustc_data_structures;
 extern crate rustc_back;
 extern crate rustc_llvm;
 extern crate rustc_const_math;
diff --git a/src/librustc_metadata/loader.rs b/src/librustc_metadata/loader.rs
index 56393b79980..edfdbf2aeef 100644
--- a/src/librustc_metadata/loader.rs
+++ b/src/librustc_metadata/loader.rs
@@ -213,8 +213,8 @@
 //! metadata::loader or metadata::creader for all the juicy details!
 
 use cstore::{MetadataBlob, MetadataVec, MetadataArchive};
+use common::{metadata_encoding_version, rustc_version};
 use decoder;
-use encoder;
 
 use rustc::hir::svh::Svh;
 use rustc::session::Session;
@@ -260,6 +260,7 @@ pub struct Context<'a> {
     pub rejected_via_hash: Vec<CrateMismatch>,
     pub rejected_via_triple: Vec<CrateMismatch>,
     pub rejected_via_kind: Vec<CrateMismatch>,
+    pub rejected_via_version: Vec<CrateMismatch>,
     pub should_match_name: bool,
 }
 
@@ -336,6 +337,10 @@ impl<'a> Context<'a> {
             struct_span_err!(self.sess, self.span, E0462,
                              "found staticlib `{}` instead of rlib or dylib{}",
                              self.ident, add)
+        } else if !self.rejected_via_version.is_empty() {
+            struct_span_err!(self.sess, self.span, E0514,
+                             "found crate `{}` compiled by an incompatible version of rustc{}",
+                             self.ident, add)
         } else {
             struct_span_err!(self.sess, self.span, E0463,
                              "can't find crate for `{}`{}",
@@ -350,7 +355,7 @@ impl<'a> Context<'a> {
             }
         }
         if !self.rejected_via_hash.is_empty() {
-            err.note("perhaps this crate needs to be recompiled?");
+            err.note("perhaps that crate needs to be recompiled?");
             let mismatches = self.rejected_via_hash.iter();
             for (i, &CrateMismatch{ ref path, .. }) in mismatches.enumerate() {
                 err.note(&format!("crate `{}` path #{}: {}",
@@ -367,13 +372,22 @@ impl<'a> Context<'a> {
             }
         }
         if !self.rejected_via_kind.is_empty() {
-            err.help("please recompile this crate using --crate-type lib");
+            err.help("please recompile that crate using --crate-type lib");
             let mismatches = self.rejected_via_kind.iter();
             for (i, &CrateMismatch { ref path, .. }) in mismatches.enumerate() {
                 err.note(&format!("crate `{}` path #{}: {}",
                                   self.ident, i+1, path.display()));
             }
         }
+        if !self.rejected_via_version.is_empty() {
+            err.help(&format!("please recompile that crate using this compiler ({})",
+                              rustc_version()));
+            let mismatches = self.rejected_via_version.iter();
+            for (i, &CrateMismatch { ref path, ref got }) in mismatches.enumerate() {
+                err.note(&format!("crate `{}` path #{}: {} compiled by {:?}",
+                                  self.ident, i+1, path.display(), got));
+            }
+        }
 
         err.emit();
         self.sess.abort_if_errors();
@@ -591,6 +605,17 @@ impl<'a> Context<'a> {
     }
 
     fn crate_matches(&mut self, crate_data: &[u8], libpath: &Path) -> Option<Svh> {
+        let crate_rustc_version = decoder::crate_rustc_version(crate_data);
+        if crate_rustc_version != Some(rustc_version()) {
+            let message = crate_rustc_version.unwrap_or(format!("an unknown compiler"));
+            info!("Rejecting via version: expected {} got {}", rustc_version(), message);
+            self.rejected_via_version.push(CrateMismatch {
+                path: libpath.to_path_buf(),
+                got: message
+            });
+            return None;
+        }
+
         if self.should_match_name {
             match decoder::maybe_get_crate_name(crate_data) {
                 Some(ref name) if self.crate_name == *name => {}
@@ -742,6 +767,21 @@ impl ArchiveMetadata {
     pub fn as_slice<'a>(&'a self) -> &'a [u8] { unsafe { &*self.data } }
 }
 
+fn verify_decompressed_encoding_version(blob: &MetadataBlob, filename: &Path)
+                                        -> Result<(), String>
+{
+    let data = blob.as_slice_raw();
+    if data.len() < 4+metadata_encoding_version.len() ||
+        !<[u8]>::eq(&data[..4], &[0, 0, 0, 0]) ||
+        &data[4..4+metadata_encoding_version.len()] != metadata_encoding_version
+    {
+        Err((format!("incompatible metadata version found: '{}'",
+                     filename.display())))
+    } else {
+        Ok(())
+    }
+}
+
 // Just a small wrapper to time how long reading metadata takes.
 fn get_metadata_section(target: &Target, flavor: CrateFlavor, filename: &Path)
                         -> Result<MetadataBlob, String> {
@@ -772,7 +812,10 @@ fn get_metadata_section_imp(target: &Target, flavor: CrateFlavor, filename: &Pat
         return match ArchiveMetadata::new(archive).map(|ar| MetadataArchive(ar)) {
             None => Err(format!("failed to read rlib metadata: '{}'",
                                 filename.display())),
-            Some(blob) => Ok(blob)
+            Some(blob) => {
+                try!(verify_decompressed_encoding_version(&blob, filename));
+                Ok(blob)
+            }
         };
     }
     unsafe {
@@ -801,12 +844,12 @@ fn get_metadata_section_imp(target: &Target, flavor: CrateFlavor, filename: &Pat
                 let cbuf = llvm::LLVMGetSectionContents(si.llsi);
                 let csz = llvm::LLVMGetSectionSize(si.llsi) as usize;
                 let cvbuf: *const u8 = cbuf as *const u8;
-                let vlen = encoder::metadata_encoding_version.len();
+                let vlen = metadata_encoding_version.len();
                 debug!("checking {} bytes of metadata-version stamp",
                        vlen);
                 let minsz = cmp::min(vlen, csz);
                 let buf0 = slice::from_raw_parts(cvbuf, minsz);
-                let version_ok = buf0 == encoder::metadata_encoding_version;
+                let version_ok = buf0 == metadata_encoding_version;
                 if !version_ok {
                     return Err((format!("incompatible metadata version found: '{}'",
                                         filename.display())));
@@ -817,7 +860,11 @@ fn get_metadata_section_imp(target: &Target, flavor: CrateFlavor, filename: &Pat
                        csz - vlen);
                 let bytes = slice::from_raw_parts(cvbuf1, csz - vlen);
                 match flate::inflate_bytes(bytes) {
-                    Ok(inflated) => return Ok(MetadataVec(inflated)),
+                    Ok(inflated) => {
+                        let blob = MetadataVec(inflated);
+                        try!(verify_decompressed_encoding_version(&blob, filename));
+                        return Ok(blob);
+                    }
                     Err(_) => {}
                 }
             }
diff --git a/src/librustc_trans/diagnostics.rs b/src/librustc_trans/diagnostics.rs
index f7f065a3562..d36878b0332 100644
--- a/src/librustc_trans/diagnostics.rs
+++ b/src/librustc_trans/diagnostics.rs
@@ -12,6 +12,44 @@
 
 register_long_diagnostics! {
 
+E0510: r##"
+`return_address` was used in an invalid context. Erroneous code example:
+
+```ignore
+#![feature(intrinsics)]
+
+extern "rust-intrinsic" {
+    fn return_address() -> *const u8;
+}
+
+unsafe fn by_value() -> i32 {
+    let _ = return_address();
+    // error: invalid use of `return_address` intrinsic: function does
+    //        not use out pointer
+    0
+}
+```
+
+Return values may be stored in a return register(s) or written into a so-called
+out pointer. In case the returned value is too big (this is
+target-ABI-dependent and generally not portable or future proof) to fit into
+the return register(s), the compiler will return the value by writing it into
+space allocated in the caller's stack frame. Example:
+
+```
+#![feature(intrinsics)]
+
+extern "rust-intrinsic" {
+    fn return_address() -> *const u8;
+}
+
+unsafe fn by_pointer() -> String {
+    let _ = return_address();
+    String::new() // ok!
+}
+```
+"##,
+
 E0511: r##"
 Invalid monomorphization of an intrinsic function was used. Erroneous code
 example:
diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs
index a721361fce0..bd24647edf0 100644
--- a/src/librustc_trans/intrinsic.rs
+++ b/src/librustc_trans/intrinsic.rs
@@ -617,6 +617,18 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
 
         },
 
+
+        (_, "return_address") => {
+            if !fcx.fn_ty.ret.is_indirect() {
+                span_err!(tcx.sess, span, E0510,
+                          "invalid use of `return_address` intrinsic: function \
+                           does not use out pointer");
+                C_null(Type::i8p(ccx))
+            } else {
+                PointerCast(bcx, llvm::get_param(fcx.llfn, 0), Type::i8p(ccx))
+            }
+        }
+
         (_, "discriminant_value") => {
             let val_ty = substs.types.get(FnSpace, 0);
             match val_ty.sty {
diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans/monomorphize.rs
index fa00ea1e780..ab859b88a85 100644
--- a/src/librustc_trans/monomorphize.rs
+++ b/src/librustc_trans/monomorphize.rs
@@ -169,8 +169,7 @@ pub struct Instance<'tcx> {
 
 impl<'tcx> fmt::Display for Instance<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        ppaux::parameterized(f, &self.substs, self.def, ppaux::Ns::Value, &[],
-                             |tcx| Some(tcx.lookup_item_type(self.def).generics))
+        ppaux::parameterized(f, &self.substs, self.def, ppaux::Ns::Value, &[], |_| None)
     }
 }
 
diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index 5a3268e9e44..0fb08ec9855 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -275,6 +275,8 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) {
             "fadd_fast" | "fsub_fast" | "fmul_fast" | "fdiv_fast" | "frem_fast" =>
                 (1, vec![param(ccx, 0), param(ccx, 0)], param(ccx, 0)),
 
+            "return_address" => (0, vec![], tcx.mk_imm_ptr(tcx.types.u8)),
+
             "assume" => (0, vec![tcx.types.bool], tcx.mk_nil()),
 
             "discriminant_value" => (1, vec![
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 83b5ab71cc2..3bc90f05d25 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1157,6 +1157,7 @@ fn check_const<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
         let rty = ccx.tcx.node_id_to_type(id);
         let fcx = FnCtxt::new(&inh, ty::FnConverging(rty), e.id);
         let declty = fcx.tcx.lookup_item_type(ccx.tcx.map.local_def_id(id)).ty;
+        fcx.require_type_is_sized(declty, e.span, traits::ConstSized);
         fcx.check_const_with_ty(sp, e, declty);
     });
 }
diff --git a/src/libstd/path.rs b/src/libstd/path.rs
index c103ff7f4b0..462e50a72cc 100644
--- a/src/libstd/path.rs
+++ b/src/libstd/path.rs
@@ -1057,7 +1057,6 @@ impl PathBuf {
         self._push(path.as_ref())
     }
 
-    #[allow(deprecated)]
     fn _push(&mut self, path: &Path) {
         // in general, a separator is needed if the rightmost byte is not a separator
         let mut need_sep = self.as_mut_vec().last().map(|c| !is_sep_byte(*c)).unwrap_or(false);
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs
index 3c88fb8f670..e01bd2a93aa 100644
--- a/src/libsyntax/attr.rs
+++ b/src/libsyntax/attr.rs
@@ -34,6 +34,27 @@ thread_local! {
     static USED_ATTRS: RefCell<Vec<u64>> = RefCell::new(Vec::new())
 }
 
+enum AttrError {
+    MultipleItem(InternedString),
+    UnknownMetaItem(InternedString),
+    MissingSince,
+    MissingFeature,
+    MultipleStabilityLevels,
+}
+
+fn handle_errors(diag: &Handler, span: Span, error: AttrError) {
+    match error {
+        AttrError::MultipleItem(item) => span_err!(diag, span, E0538,
+                                                   "multiple '{}' items", item),
+        AttrError::UnknownMetaItem(item) => span_err!(diag, span, E0541,
+                                                      "unknown meta item '{}'", item),
+        AttrError::MissingSince => span_err!(diag, span, E0542, "missing 'since'"),
+        AttrError::MissingFeature => span_err!(diag, span, E0546, "missing 'feature'"),
+        AttrError::MultipleStabilityLevels => span_err!(diag, span, E0544,
+                                                        "multiple stability levels"),
+    }
+}
+
 pub fn mark_used(attr: &Attribute) {
     let AttrId(id) = attr.node.id;
     USED_ATTRS.with(|slot| {
@@ -303,10 +324,10 @@ pub fn find_export_name_attr(diag: &Handler, attrs: &[Attribute]) -> Option<Inte
             if let s@Some(_) = attr.value_str() {
                 s
             } else {
-                diag.struct_span_err(attr.span,
-                                     "export_name attribute has invalid format")
-                    .help("use #[export_name=\"*\"]")
-                    .emit();
+                struct_span_err!(diag, attr.span, E0533,
+                                 "export_name attribute has invalid format")
+                                .help("use #[export_name=\"*\"]")
+                                .emit();
                 None
             }
         } else {
@@ -339,14 +360,16 @@ pub fn find_inline_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> In
             MetaItemKind::List(ref n, ref items) if n == "inline" => {
                 mark_used(attr);
                 if items.len() != 1 {
-                    diagnostic.map(|d|{ d.span_err(attr.span, "expected one argument"); });
+                    diagnostic.map(|d|{ span_err!(d, attr.span, E0534, "expected one argument"); });
                     InlineAttr::None
                 } else if contains_name(&items[..], "always") {
                     InlineAttr::Always
                 } else if contains_name(&items[..], "never") {
                     InlineAttr::Never
                 } else {
-                    diagnostic.map(|d|{ d.span_err((*items[0]).span, "invalid argument"); });
+                    diagnostic.map(|d| {
+                        span_err!(d, (*items[0]).span, E0535, "invalid argument");
+                    });
                     InlineAttr::None
                 }
             }
@@ -374,13 +397,13 @@ pub fn cfg_matches(cfgs: &[P<MetaItem>], cfg: &ast::MetaItem,
             mis.iter().all(|mi| cfg_matches(cfgs, &mi, sess, features)),
         ast::MetaItemKind::List(ref pred, ref mis) if &pred[..] == "not" => {
             if mis.len() != 1 {
-                sess.span_diagnostic.span_err(cfg.span, "expected 1 cfg-pattern");
+                span_err!(sess.span_diagnostic, cfg.span, E0536, "expected 1 cfg-pattern");
                 return false;
             }
             !cfg_matches(cfgs, &mis[0], sess, features)
         }
         ast::MetaItemKind::List(ref pred, _) => {
-            sess.span_diagnostic.span_err(cfg.span, &format!("invalid predicate `{}`", pred));
+            span_err!(sess.span_diagnostic, cfg.span, E0537, "invalid predicate `{}`", pred);
             false
         },
         ast::MetaItemKind::Word(_) | ast::MetaItemKind::NameValue(..) => {
@@ -446,15 +469,14 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
         if let Some(metas) = attr.meta_item_list() {
             let get = |meta: &MetaItem, item: &mut Option<InternedString>| {
                 if item.is_some() {
-                    diagnostic.span_err(meta.span, &format!("multiple '{}' items",
-                                                             meta.name()));
+                    handle_errors(diagnostic, meta.span, AttrError::MultipleItem(meta.name()));
                     return false
                 }
                 if let Some(v) = meta.value_str() {
                     *item = Some(v);
                     true
                 } else {
-                    diagnostic.span_err(meta.span, "incorrect meta item");
+                    span_err!(diagnostic, meta.span, E0539, "incorrect meta item");
                     false
                 }
             };
@@ -462,7 +484,8 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
             match tag {
                 "rustc_deprecated" => {
                     if rustc_depr.is_some() {
-                        diagnostic.span_err(item_sp, "multiple rustc_deprecated attributes");
+                        span_err!(diagnostic, item_sp, E0540,
+                                  "multiple rustc_deprecated attributes");
                         break
                     }
 
@@ -473,8 +496,8 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                             "since" => if !get(meta, &mut since) { continue 'outer },
                             "reason" => if !get(meta, &mut reason) { continue 'outer },
                             _ => {
-                                diagnostic.span_err(meta.span, &format!("unknown meta item '{}'",
-                                                                        meta.name()));
+                                handle_errors(diagnostic, meta.span,
+                                              AttrError::UnknownMetaItem(meta.name()));
                                 continue 'outer
                             }
                         }
@@ -488,18 +511,18 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                             })
                         }
                         (None, _) => {
-                            diagnostic.span_err(attr.span(), "missing 'since'");
+                            handle_errors(diagnostic, attr.span(), AttrError::MissingSince);
                             continue
                         }
                         _ => {
-                            diagnostic.span_err(attr.span(), "missing 'reason'");
+                            span_err!(diagnostic, attr.span(), E0543, "missing 'reason'");
                             continue
                         }
                     }
                 }
                 "unstable" => {
                     if stab.is_some() {
-                        diagnostic.span_err(item_sp, "multiple stability levels");
+                        handle_errors(diagnostic, attr.span(), AttrError::MultipleStabilityLevels);
                         break
                     }
 
@@ -512,8 +535,8 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                             "reason" => if !get(meta, &mut reason) { continue 'outer },
                             "issue" => if !get(meta, &mut issue) { continue 'outer },
                             _ => {
-                                diagnostic.span_err(meta.span, &format!("unknown meta item '{}'",
-                                                                        meta.name()));
+                                handle_errors(diagnostic, meta.span,
+                                              AttrError::UnknownMetaItem(meta.name()));
                                 continue 'outer
                             }
                         }
@@ -528,7 +551,8 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                                         if let Ok(issue) = issue.parse() {
                                             issue
                                         } else {
-                                            diagnostic.span_err(attr.span(), "incorrect 'issue'");
+                                            span_err!(diagnostic, attr.span(), E0545,
+                                                      "incorrect 'issue'");
                                             continue
                                         }
                                     }
@@ -538,18 +562,18 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                             })
                         }
                         (None, _, _) => {
-                            diagnostic.span_err(attr.span(), "missing 'feature'");
+                            handle_errors(diagnostic, attr.span(), AttrError::MissingFeature);
                             continue
                         }
                         _ => {
-                            diagnostic.span_err(attr.span(), "missing 'issue'");
+                            span_err!(diagnostic, attr.span(), E0547, "missing 'issue'");
                             continue
                         }
                     }
                 }
                 "stable" => {
                     if stab.is_some() {
-                        diagnostic.span_err(item_sp, "multiple stability levels");
+                        handle_errors(diagnostic, attr.span(), AttrError::MultipleStabilityLevels);
                         break
                     }
 
@@ -560,8 +584,8 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                             "feature" => if !get(meta, &mut feature) { continue 'outer },
                             "since" => if !get(meta, &mut since) { continue 'outer },
                             _ => {
-                                diagnostic.span_err(meta.span, &format!("unknown meta item '{}'",
-                                                                        meta.name()));
+                                handle_errors(diagnostic, meta.span,
+                                              AttrError::UnknownMetaItem(meta.name()));
                                 continue 'outer
                             }
                         }
@@ -578,11 +602,11 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                             })
                         }
                         (None, _) => {
-                            diagnostic.span_err(attr.span(), "missing 'feature'");
+                            handle_errors(diagnostic, attr.span(), AttrError::MissingFeature);
                             continue
                         }
                         _ => {
-                            diagnostic.span_err(attr.span(), "missing 'since'");
+                            handle_errors(diagnostic, attr.span(), AttrError::MissingSince);
                             continue
                         }
                     }
@@ -590,7 +614,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                 _ => unreachable!()
             }
         } else {
-            diagnostic.span_err(attr.span(), "incorrect stability attribute type");
+            span_err!(diagnostic, attr.span(), E0548, "incorrect stability attribute type");
             continue
         }
     }
@@ -603,8 +627,9 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
             }
             stab.rustc_depr = Some(rustc_depr);
         } else {
-            diagnostic.span_err(item_sp, "rustc_deprecated attribute must be paired with \
-                                          either stable or unstable attribute");
+            span_err!(diagnostic, item_sp, E0549,
+                      "rustc_deprecated attribute must be paired with \
+                       either stable or unstable attribute");
         }
     }
 
@@ -627,22 +652,21 @@ fn find_deprecation_generic<'a, I>(diagnostic: &Handler,
         mark_used(attr);
 
         if depr.is_some() {
-            diagnostic.span_err(item_sp, "multiple deprecated attributes");
+            span_err!(diagnostic, item_sp, E0550, "multiple deprecated attributes");
             break
         }
 
         depr = if let Some(metas) = attr.meta_item_list() {
             let get = |meta: &MetaItem, item: &mut Option<InternedString>| {
                 if item.is_some() {
-                    diagnostic.span_err(meta.span, &format!("multiple '{}' items",
-                                                             meta.name()));
+                    handle_errors(diagnostic, meta.span, AttrError::MultipleItem(meta.name()));
                     return false
                 }
                 if let Some(v) = meta.value_str() {
                     *item = Some(v);
                     true
                 } else {
-                    diagnostic.span_err(meta.span, "incorrect meta item");
+                    span_err!(diagnostic, meta.span, E0551, "incorrect meta item");
                     false
                 }
             };
@@ -654,8 +678,8 @@ fn find_deprecation_generic<'a, I>(diagnostic: &Handler,
                     "since" => if !get(meta, &mut since) { continue 'outer },
                     "note" => if !get(meta, &mut note) { continue 'outer },
                     _ => {
-                        diagnostic.span_err(meta.span, &format!("unknown meta item '{}'",
-                                                                meta.name()));
+                        handle_errors(diagnostic, meta.span,
+                                      AttrError::UnknownMetaItem(meta.name()));
                         continue 'outer
                     }
                 }
@@ -689,7 +713,7 @@ pub fn require_unique_names(diagnostic: &Handler, metas: &[P<MetaItem>]) {
 
         if !set.insert(name.clone()) {
             panic!(diagnostic.span_fatal(meta.span,
-                                  &format!("duplicate meta item `{}`", name)));
+                                         &format!("duplicate meta item `{}`", name)));
         }
     }
 }
@@ -718,8 +742,8 @@ pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec<ReprAttr>
                                 Some(ity) => Some(ReprInt(item.span, ity)),
                                 None => {
                                     // Not a word we recognize
-                                    diagnostic.span_err(item.span,
-                                                        "unrecognized representation hint");
+                                    span_err!(diagnostic, item.span, E0552,
+                                              "unrecognized representation hint");
                                     None
                                 }
                             }
@@ -731,7 +755,8 @@ pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec<ReprAttr>
                         }
                     }
                     // Not a word:
-                    _ => diagnostic.span_err(item.span, "unrecognized enum representation hint")
+                    _ => span_err!(diagnostic, item.span, E0553,
+                                   "unrecognized enum representation hint"),
                 }
             }
         }
diff --git a/src/libsyntax/diagnostic_list.rs b/src/libsyntax/diagnostic_list.rs
new file mode 100644
index 00000000000..eb30657bd56
--- /dev/null
+++ b/src/libsyntax/diagnostic_list.rs
@@ -0,0 +1,54 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(non_snake_case)]
+
+// Error messages for EXXXX errors.
+// Each message should start and end with a new line, and be wrapped to 80 characters.
+// In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use `:set tw=0` to disable.
+register_long_diagnostics! {
+
+E0533: r##"
+```compile_fail,E0533
+#[export_name]
+pub fn something() {}
+
+fn main() {}
+```
+"##,
+
+}
+
+register_diagnostics! {
+    E0534, // expected one argument
+    E0535, // invalid argument
+    E0536, // expected 1 cfg-pattern
+    E0537, // invalid predicate
+    E0538, // multiple [same] items
+    E0539, // incorrect meta item
+    E0540, // multiple rustc_deprecated attributes
+    E0541, // unknown meta item
+    E0542, // missing 'since'
+    E0543, // missing 'reason'
+    E0544, // multiple stability levels
+    E0545, // incorrect 'issue'
+    E0546, // missing 'feature'
+    E0547, // missing 'issue'
+    E0548, // incorrect stability attribute type
+    E0549, // rustc_deprecated attribute must be paired with either stable or unstable attribute
+    E0550, // multiple deprecated attributes
+    E0551, // incorrect meta item
+    E0552, // unrecognized representation hint
+    E0553, // unrecognized enum representation hint
+    E0554, // #[feature] may not be used on the [] release channel
+    E0555, // malformed feature attribute, expected #![feature(...)]
+    E0556, // malformed feature, expected just one word
+    E0557, // feature has been removed
+}
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index d6476fdb2f0..27485ee65fc 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -1103,17 +1103,16 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute]) -> F
 
         match attr.meta_item_list() {
             None => {
-                span_handler.span_err(attr.span, "malformed feature attribute, \
-                                                  expected #![feature(...)]");
+                span_err!(span_handler, attr.span, E0555,
+                          "malformed feature attribute, expected #![feature(...)]");
             }
             Some(list) => {
                 for mi in list {
                     let name = match mi.node {
                         ast::MetaItemKind::Word(ref word) => (*word).clone(),
                         _ => {
-                            span_handler.span_err(mi.span,
-                                                  "malformed feature, expected just \
-                                                   one word");
+                            span_err!(span_handler, mi.span, E0556,
+                                      "malformed feature, expected just one word");
                             continue
                         }
                     };
@@ -1123,7 +1122,7 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute]) -> F
                     }
                     else if let Some(&(_, _, _)) = REMOVED_FEATURES.iter()
                         .find(|& &(n, _, _)| name == n) {
-                        span_handler.span_err(mi.span, "feature has been removed");
+                        span_err!(span_handler, mi.span, E0557, "feature has been removed");
                     }
                     else if let Some(&(_, _, _)) = ACCEPTED_FEATURES.iter()
                         .find(|& &(n, _, _)| name == n) {
@@ -1179,9 +1178,9 @@ fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate,
         for attr in &krate.attrs {
             if attr.check_name("feature") {
                 let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)");
-                let ref msg = format!("#[feature] may not be used on the {} release channel",
-                                      release_channel);
-                span_handler.span_err(attr.span, msg);
+                span_err!(span_handler, attr.span, E0554,
+                          "#[feature] may not be used on the {} release channel",
+                          release_channel);
             }
         }
     }
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index 652cf68db07..8febf1c49ec 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -33,6 +33,7 @@
 #![feature(str_escape)]
 #![feature(unicode)]
 #![feature(question_mark)]
+#![feature(rustc_diagnostic_macros)]
 
 extern crate serialize;
 extern crate term;
@@ -66,6 +67,18 @@ macro_rules! panictry {
     })
 }
 
+#[macro_use]
+pub mod diagnostics {
+    #[macro_use]
+    pub mod macros;
+    pub mod plugin;
+    pub mod metadata;
+}
+
+// NB: This module needs to be declared first so diagnostics are
+// registered before they are used.
+pub mod diagnostic_list;
+
 pub mod util {
     pub mod interner;
     pub mod lev_distance;
@@ -80,12 +93,6 @@ pub mod util {
     pub use self::thin_vec::ThinVec;
 }
 
-pub mod diagnostics {
-    pub mod macros;
-    pub mod plugin;
-    pub mod metadata;
-}
-
 pub mod json;
 
 pub mod syntax {
@@ -130,3 +137,5 @@ pub mod ext {
         pub mod macro_rules;
     }
 }
+
+// __build_diagnostic_array! { libsyntax, DIAGNOSTICS }
diff --git a/src/rustc/Cargo.lock b/src/rustc/Cargo.lock
index 9c6ed991df8..c9d1eb39f0a 100644
--- a/src/rustc/Cargo.lock
+++ b/src/rustc/Cargo.lock
@@ -213,6 +213,7 @@ dependencies = [
  "rustc_back 0.0.0",
  "rustc_bitflags 0.0.0",
  "rustc_const_math 0.0.0",
+ "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
  "rustc_llvm 0.0.0",
  "serialize 0.0.0",
diff --git a/src/test/compile-fail/changing-crates.rs b/src/test/compile-fail/changing-crates.rs
index 0b420158488..f74855a0849 100644
--- a/src/test/compile-fail/changing-crates.rs
+++ b/src/test/compile-fail/changing-crates.rs
@@ -17,7 +17,7 @@
 
 extern crate a;
 extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on
-//~| NOTE: perhaps this crate needs to be recompiled
+//~| NOTE: perhaps that crate needs to be recompiled
 //~| NOTE: crate `a` path #1:
 //~| NOTE: crate `b` path #1:
 
diff --git a/src/test/compile-fail/const-unsized.rs b/src/test/compile-fail/const-unsized.rs
new file mode 100644
index 00000000000..72a5c5fff60
--- /dev/null
+++ b/src/test/compile-fail/const-unsized.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 std::fmt::Debug;
+
+const CONST_0: Debug+Sync = *(&0 as &(Debug+Sync));
+//~^ ERROR `std::fmt::Debug + Sync + 'static: std::marker::Sized` is not satisfied
+//~| NOTE does not have a constant size known at compile-time
+//~| NOTE constant expressions must have a statically known size
+
+const CONST_FOO: str = *"foo";
+//~^ ERROR `str: std::marker::Sized` is not satisfied
+//~| NOTE does not have a constant size known at compile-time
+//~| NOTE constant expressions must have a statically known size
+
+static STATIC_1: Debug+Sync = *(&1 as &(Debug+Sync));
+//~^ ERROR `std::fmt::Debug + Sync + 'static: std::marker::Sized` is not satisfied
+//~| NOTE does not have a constant size known at compile-time
+//~| NOTE constant expressions must have a statically known size
+
+static STATIC_BAR: str = *"bar";
+//~^ ERROR `str: std::marker::Sized` is not satisfied
+//~| NOTE does not have a constant size known at compile-time
+//~| NOTE constant expressions must have a statically known size
+
+fn main() {
+    println!("{:?} {:?} {:?} {:?}", &CONST_0, &CONST_FOO, &STATIC_1, &STATIC_BAR);
+}
diff --git a/src/test/compile-fail/intrinsic-return-address.rs b/src/test/compile-fail/intrinsic-return-address.rs
new file mode 100644
index 00000000000..906056896be
--- /dev/null
+++ b/src/test/compile-fail/intrinsic-return-address.rs
@@ -0,0 +1,24 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(warnings)]
+#![feature(intrinsics)]
+
+extern "rust-intrinsic" {
+    fn return_address() -> *const u8;
+}
+
+unsafe fn f() { let _ = return_address(); }
+//~^ ERROR invalid use of `return_address` intrinsic: function does not use out pointer
+
+unsafe fn g() -> isize { let _ = return_address(); 0 }
+//~^ ERROR invalid use of `return_address` intrinsic: function does not use out pointer
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-24446.rs b/src/test/compile-fail/issue-24446.rs
index cbeac774798..b9382520cf9 100644
--- a/src/test/compile-fail/issue-24446.rs
+++ b/src/test/compile-fail/issue-24446.rs
@@ -11,6 +11,8 @@
 fn main() {
     static foo: Fn() -> u32 = || -> u32 {
         //~^ ERROR: mismatched types
+        //~| ERROR: `std::ops::Fn() -> u32 + 'static: std::marker::Sized` is not satisfied
+
         0
     };
 }
diff --git a/src/test/compile-fail/stability-attribute-sanity.rs b/src/test/compile-fail/stability-attribute-sanity.rs
index 8c7c0c275db..d35f2cbb584 100644
--- a/src/test/compile-fail/stability-attribute-sanity.rs
+++ b/src/test/compile-fail/stability-attribute-sanity.rs
@@ -15,83 +15,84 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 mod bogus_attribute_types_1 {
-    #[stable(feature = "a", since = "a", reason)] //~ ERROR unknown meta item 'reason'
+    #[stable(feature = "a", since = "a", reason)] //~ ERROR unknown meta item 'reason' [E0541]
     fn f1() { }
 
-    #[stable(feature = "a", since)] //~ ERROR incorrect meta item
+    #[stable(feature = "a", since)] //~ ERROR incorrect meta item [E0539]
     fn f2() { }
 
-    #[stable(feature, since = "a")] //~ ERROR incorrect meta item
+    #[stable(feature, since = "a")] //~ ERROR incorrect meta item [E0539]
     fn f3() { }
 
-    #[stable(feature = "a", since(b))] //~ ERROR incorrect meta item
+    #[stable(feature = "a", since(b))] //~ ERROR incorrect meta item [E0539]
     fn f5() { }
 
-    #[stable(feature(b), since = "a")] //~ ERROR incorrect meta item
+    #[stable(feature(b), since = "a")] //~ ERROR incorrect meta item [E0539]
     fn f6() { }
 }
 
 mod bogus_attribute_types_2 {
-    #[unstable] //~ ERROR incorrect stability attribute type
+    #[unstable] //~ ERROR incorrect stability attribute type [E0548]
     fn f1() { }
 
-    #[unstable = "a"] //~ ERROR incorrect stability attribute type
+    #[unstable = "a"] //~ ERROR incorrect stability attribute type [E0548]
     fn f2() { }
 
-    #[stable] //~ ERROR incorrect stability attribute type
+    #[stable] //~ ERROR incorrect stability attribute type [E0548]
     fn f3() { }
 
-    #[stable = "a"] //~ ERROR incorrect stability attribute type
+    #[stable = "a"] //~ ERROR incorrect stability attribute type [E0548]
     fn f4() { }
 
     #[stable(feature = "a", since = "b")]
-    #[rustc_deprecated] //~ ERROR incorrect stability attribute type
+    #[rustc_deprecated] //~ ERROR incorrect stability attribute type [E0548]
     fn f5() { }
 
     #[stable(feature = "a", since = "b")]
-    #[rustc_deprecated = "a"] //~ ERROR incorrect stability attribute type
+    #[rustc_deprecated = "a"] //~ ERROR incorrect stability attribute type [E0548]
     fn f6() { }
 }
 
 mod missing_feature_names {
-    #[unstable(issue = "0")] //~ ERROR missing 'feature'
+    #[unstable(issue = "0")] //~ ERROR missing 'feature' [E0546]
     fn f1() { }
 
-    #[unstable(feature = "a")] //~ ERROR missing 'issue'
+    #[unstable(feature = "a")] //~ ERROR missing 'issue' [E0547]
     fn f2() { }
 
-    #[stable(since = "a")] //~ ERROR missing 'feature'
+    #[stable(since = "a")] //~ ERROR missing 'feature' [E0546]
     fn f3() { }
 }
 
 mod missing_version {
-    #[stable(feature = "a")] //~ ERROR missing 'since'
+    #[stable(feature = "a")] //~ ERROR missing 'since' [E0542]
     fn f1() { }
 
     #[stable(feature = "a", since = "b")]
-    #[rustc_deprecated(reason = "a")] //~ ERROR missing 'since'
+    #[rustc_deprecated(reason = "a")] //~ ERROR missing 'since' [E0542]
     fn f2() { }
 }
 
 #[unstable(feature = "a", issue = "0")]
-#[stable(feature = "a", since = "b")]
-fn multiple1() { } //~ ERROR multiple stability levels
+#[stable(feature = "a", since = "b")] //~ ERROR multiple stability levels [E0544]
+fn multiple1() { }
 
 #[unstable(feature = "a", issue = "0")]
-#[unstable(feature = "a", issue = "0")]
-fn multiple2() { } //~ ERROR multiple stability levels
+#[unstable(feature = "a", issue = "0")] //~ ERROR multiple stability levels [E0544]
+fn multiple2() { }
 
 #[stable(feature = "a", since = "b")]
-#[stable(feature = "a", since = "b")]
-fn multiple3() { } //~ ERROR multiple stability levels
+#[stable(feature = "a", since = "b")] //~ ERROR multiple stability levels [E0544]
+fn multiple3() { }
 
 #[stable(feature = "a", since = "b")]
 #[rustc_deprecated(since = "b", reason = "text")]
 #[rustc_deprecated(since = "b", reason = "text")]
-fn multiple4() { } //~ ERROR multiple rustc_deprecated attributes
+fn multiple4() { } //~ ERROR multiple rustc_deprecated attributes [E0540]
 //~^ ERROR Invalid stability or deprecation version found
 
 #[rustc_deprecated(since = "a", reason = "text")]
-fn deprecated_without_unstable_or_stable() { } //~ ERROR rustc_deprecated attribute must be paired
+fn deprecated_without_unstable_or_stable() { }
+//~^ ERROR rustc_deprecated attribute must be paired with either stable or unstable attribute
 
 fn main() { }
diff --git a/src/test/compile-fail/svh-change-lit.rs b/src/test/compile-fail/svh-change-lit.rs
index eb92bcf065d..1638caaa923 100644
--- a/src/test/compile-fail/svh-change-lit.rs
+++ b/src/test/compile-fail/svh-change-lit.rs
@@ -17,7 +17,7 @@
 
 extern crate a;
 extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on
-//~| NOTE: perhaps this crate needs to be recompiled
+//~| NOTE: perhaps that crate needs to be recompiled
 //~| NOTE: crate `a` path #1:
 //~| NOTE: crate `b` path #1:
 
diff --git a/src/test/compile-fail/svh-change-significant-cfg.rs b/src/test/compile-fail/svh-change-significant-cfg.rs
index 7c9e0d3a92c..99523ca699f 100644
--- a/src/test/compile-fail/svh-change-significant-cfg.rs
+++ b/src/test/compile-fail/svh-change-significant-cfg.rs
@@ -17,7 +17,7 @@
 
 extern crate a;
 extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on
-//~| NOTE: perhaps this crate needs to be recompiled
+//~| NOTE: perhaps that crate needs to be recompiled
 //~| NOTE: crate `a` path #1:
 //~| NOTE: crate `b` path #1:
 
diff --git a/src/test/compile-fail/svh-change-trait-bound.rs b/src/test/compile-fail/svh-change-trait-bound.rs
index 1e6a7232904..dcf4859792d 100644
--- a/src/test/compile-fail/svh-change-trait-bound.rs
+++ b/src/test/compile-fail/svh-change-trait-bound.rs
@@ -17,7 +17,7 @@
 
 extern crate a;
 extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on
-//~| NOTE: perhaps this crate needs to be recompiled
+//~| NOTE: perhaps that crate needs to be recompiled
 //~| NOTE: crate `a` path #1:
 //~| NOTE: crate `b` path #1:
 
diff --git a/src/test/compile-fail/svh-change-type-arg.rs b/src/test/compile-fail/svh-change-type-arg.rs
index 73c35ee6f82..7e51ca456b2 100644
--- a/src/test/compile-fail/svh-change-type-arg.rs
+++ b/src/test/compile-fail/svh-change-type-arg.rs
@@ -17,7 +17,7 @@
 
 extern crate a;
 extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on
-//~| NOTE: perhaps this crate needs to be recompiled
+//~| NOTE: perhaps that crate needs to be recompiled
 //~| NOTE: crate `a` path #1:
 //~| NOTE: crate `b` path #1:
 
diff --git a/src/test/compile-fail/svh-change-type-ret.rs b/src/test/compile-fail/svh-change-type-ret.rs
index b8908e2cbd1..54ca87d84c1 100644
--- a/src/test/compile-fail/svh-change-type-ret.rs
+++ b/src/test/compile-fail/svh-change-type-ret.rs
@@ -17,7 +17,7 @@
 
 extern crate a;
 extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on
-//~| NOTE: perhaps this crate needs to be recompiled
+//~| NOTE: perhaps that crate needs to be recompiled
 //~| NOTE: crate `a` path #1:
 //~| NOTE: crate `b` path #1:
 
diff --git a/src/test/compile-fail/svh-change-type-static.rs b/src/test/compile-fail/svh-change-type-static.rs
index 291e441aa5e..ea90faaf610 100644
--- a/src/test/compile-fail/svh-change-type-static.rs
+++ b/src/test/compile-fail/svh-change-type-static.rs
@@ -17,7 +17,7 @@
 
 extern crate a;
 extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on
-//~| NOTE: perhaps this crate needs to be recompiled
+//~| NOTE: perhaps that crate needs to be recompiled
 //~| NOTE: crate `a` path #1:
 //~| NOTE: crate `b` path #1:
 
diff --git a/src/test/compile-fail/svh-use-trait.rs b/src/test/compile-fail/svh-use-trait.rs
index ed816a93c52..c0a5a0a17eb 100644
--- a/src/test/compile-fail/svh-use-trait.rs
+++ b/src/test/compile-fail/svh-use-trait.rs
@@ -22,7 +22,7 @@
 
 extern crate uta;
 extern crate utb; //~ ERROR: found possibly newer version of crate `uta` which `utb` depends
-//~| NOTE: perhaps this crate needs to be recompiled?
+//~| NOTE: perhaps that crate needs to be recompiled?
 //~| NOTE: crate `uta` path #1:
 //~| NOTE: crate `utb` path #1:
 
diff --git a/src/test/run-make/many-crates-but-no-match/Makefile b/src/test/run-make/many-crates-but-no-match/Makefile
index edf8e9df465..0da4af34ef0 100644
--- a/src/test/run-make/many-crates-but-no-match/Makefile
+++ b/src/test/run-make/many-crates-but-no-match/Makefile
@@ -28,7 +28,7 @@ all:
 	# Ensure crateC fails to compile since A1 is "missing" and A2/A3 hashes do not match
 	$(RUSTC) -L $(A2) -L $(A3) crateC.rs >$(LOG) 2>&1 || true
 	grep "error: found possibly newer version of crate \`crateA\` which \`crateB\` depends on" $(LOG)
-	grep "note: perhaps this crate needs to be recompiled?" $(LOG)
+	grep "note: perhaps that crate needs to be recompiled?" $(LOG)
 	grep "note: crate \`crateA\` path #1:" $(LOG)
 	grep "note: crate \`crateA\` path #2:" $(LOG)
 	grep "note: crate \`crateB\` path #1:" $(LOG)
diff --git a/src/test/run-pass/intrinsic-return-address.rs b/src/test/run-pass/intrinsic-return-address.rs
new file mode 100644
index 00000000000..63aed3f009f
--- /dev/null
+++ b/src/test/run-pass/intrinsic-return-address.rs
@@ -0,0 +1,43 @@
+// Copyright 2012-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.
+
+
+#![feature(intrinsics)]
+
+use std::ptr;
+
+struct Point {
+    x: f32,
+    y: f32,
+    z: f32,
+}
+
+extern "rust-intrinsic" {
+    fn return_address() -> *const u8;
+}
+
+fn f(result: &mut usize) -> Point {
+    unsafe {
+        *result = return_address() as usize;
+        Point {
+            x: 1.0,
+            y: 2.0,
+            z: 3.0,
+        }
+    }
+
+}
+
+fn main() {
+    let mut intrinsic_reported_address = 0;
+    let pt = f(&mut intrinsic_reported_address);
+    let actual_address = &pt as *const Point as usize;
+    assert_eq!(intrinsic_reported_address, actual_address);
+}
diff --git a/src/test/run-pass/issue-34503.rs b/src/test/run-pass/issue-34503.rs
new file mode 100644
index 00000000000..e6217243eeb
--- /dev/null
+++ b/src/test/run-pass/issue-34503.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.
+
+fn main() {
+    struct X;
+    trait Foo<T> {
+        fn foo(&self) where (T, Option<T>): Ord {}
+        fn bar(&self, x: &Option<T>) -> bool
+        where Option<T>: Ord { *x < *x }
+    }
+    impl Foo<X> for () {}
+    let _ = &() as &Foo<X>;
+}
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 953e060465a..577da5c5af1 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1012,8 +1012,7 @@ actual:\n\
 
         // Parse the JSON output from the compiler and extract out the messages.
         let actual_errors = json::parse_output(&file_name, &proc_res.stderr, &proc_res);
-        let mut unexpected = 0;
-        let mut not_found = 0;
+        let mut unexpected = Vec::new();
         let mut found = vec![false; expected_errors.len()];
         for actual_error in &actual_errors {
             let opt_index =
@@ -1045,12 +1044,13 @@ actual:\n\
                                      .map_or(String::from("message"),
                                              |k| k.to_string()),
                                      actual_error.msg));
-                        unexpected += 1;
+                        unexpected.push(actual_error.clone());
                     }
                 }
             }
         }
 
+        let mut not_found = Vec::new();
         // anything not yet found is a problem
         for (index, expected_error) in expected_errors.iter().enumerate() {
             if !found[index] {
@@ -1062,18 +1062,22 @@ actual:\n\
                              .map_or("message".into(),
                                      |k| k.to_string()),
                              expected_error.msg));
-                not_found += 1;
+                not_found.push(expected_error.clone());
             }
         }
 
-        if unexpected > 0 || not_found > 0 {
+        if unexpected.len() > 0 || not_found.len() > 0 {
             self.error(
                 &format!("{} unexpected errors found, {} expected errors not found",
-                         unexpected, not_found));
+                         unexpected.len(), not_found.len()));
             print!("status: {}\ncommand: {}\n",
                    proc_res.status, proc_res.cmdline);
-            println!("actual errors (from JSON output): {:#?}\n", actual_errors);
-            println!("expected errors (from test file): {:#?}\n", expected_errors);
+            if unexpected.len() > 0 {
+                println!("unexpected errors (from JSON output): {:#?}\n", unexpected);
+            }
+            if not_found.len() > 0 {
+                println!("not found errors (from test file): {:#?}\n", not_found);
+            }
             panic!();
         }
     }
diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs
index 4b74833eaf7..80c37d55975 100644
--- a/src/tools/linkchecker/main.rs
+++ b/src/tools/linkchecker/main.rs
@@ -138,22 +138,6 @@ fn check(cache: &mut Cache,
         return None;
     }
 
-    if file.ends_with("std/sys/ext/index.html") {
-        return None;
-    }
-
-    if let Some(file) = file.to_str() {
-        // FIXME(#31948)
-        if file.contains("ParseFloatError") {
-            return None;
-        }
-        // weird reexports, but this module is on its way out, so chalk it up to
-        // "rustdoc weirdness" and move on from there
-        if file.contains("scoped_tls") {
-            return None;
-        }
-    }
-
     let mut parser = UrlParser::new();
     parser.base_url(base);
 
@@ -170,12 +154,24 @@ fn check(cache: &mut Cache,
 
     // Search for anything that's the regex 'href[ ]*=[ ]*".*?"'
     with_attrs_in_source(&contents, " href", |url, i| {
+        // Ignore external URLs
+        if url.starts_with("http:") || url.starts_with("https:") ||
+           url.starts_with("javascript:") || url.starts_with("ftp:") ||
+           url.starts_with("irc:") || url.starts_with("data:") {
+            return;
+        }
         // Once we've plucked out the URL, parse it using our base url and
-        // then try to extract a file path. If either of these fail then we
-        // just keep going.
+        // then try to extract a file path.
         let (parsed_url, path) = match url_to_file_path(&parser, url) {
             Some((url, path)) => (url, PathBuf::from(path)),
-            None => return,
+            None => {
+                *errors = true;
+                println!("{}:{}: invalid link - {}",
+                         pretty_file.display(),
+                         i + 1,
+                         url);
+                return;
+            }
         };
 
         // Alright, if we've found a file name then this file had better
@@ -197,10 +193,11 @@ fn check(cache: &mut Cache,
                 Ok(res) => res,
                 Err(LoadError::IOError(err)) => panic!(format!("{}", err)),
                 Err(LoadError::BrokenRedirect(target, _)) => {
-                    print!("{}:{}: broken redirect to {}",
-                           pretty_file.display(),
-                           i + 1,
-                           target.display());
+                    *errors = true;
+                    println!("{}:{}: broken redirect to {}",
+                             pretty_file.display(),
+                             i + 1,
+                             target.display());
                     return;
                 }
                 Err(LoadError::IsRedirect) => unreachable!(),