about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-02-25 12:29:32 +0000
committerbors <bors@rust-lang.org>2017-02-25 12:29:32 +0000
commit1572bf104dbf65d58bd6b889fa46229c9b92d6f9 (patch)
tree0cd0f02c7a7634ab5e86d2e14f74aeaf4758382e
parente78aa5d7546d5db493ec12328368ab0c249c2a94 (diff)
parent207c76306037776c0e72456d5a0497e430c6753c (diff)
downloadrust-1572bf104dbf65d58bd6b889fa46229c9b92d6f9.tar.gz
rust-1572bf104dbf65d58bd6b889fa46229c9b92d6f9.zip
Auto merge of #40091 - eddyb:rollup, r=eddyb
Rollup of 28 pull requests

- Successful merges: #39859, #39864, #39888, #39903, #39905, #39914, #39945, #39950, #39953, #39961, #39980, #39988, #39993, #39995, #40019, #40020, #40022, #40024, #40025, #40026, #40027, #40031, #40035, #40037, #40038, #40064, #40069, #40086
- Failed merges: #39927, #40008, #40047
-rw-r--r--src/bootstrap/bin/rustc.rs18
-rw-r--r--src/bootstrap/bootstrap.py10
-rw-r--r--src/bootstrap/flags.rs3
-rw-r--r--src/bootstrap/lib.rs15
-rw-r--r--src/ci/docker/linux-tested-targets/Dockerfile8
-rw-r--r--src/ci/docker/linux-tested-targets/build-musl.sh5
-rw-r--r--src/doc/nomicon/src/phantom-data.md22
-rw-r--r--src/libcompiler_builtins/build.rs10
m---------src/liblibc0
-rw-r--r--src/librustc/cfg/construct.rs36
-rw-r--r--src/librustc/hir/def.rs5
-rw-r--r--src/librustc/hir/intravisit.rs24
-rw-r--r--src/librustc/hir/lowering.rs172
-rw-r--r--src/librustc/hir/mod.rs58
-rw-r--r--src/librustc/hir/print.rs12
-rw-r--r--src/librustc/infer/error_reporting.rs53
-rw-r--r--src/librustc/middle/expr_use_visitor.rs1
-rw-r--r--src/librustc/middle/liveness.rs45
-rw-r--r--src/librustc/middle/mem_categorization.rs1
-rw-r--r--src/librustc/mir/mod.rs3
-rw-r--r--src/librustc/session/config.rs73
-rw-r--r--src/librustc/session/mod.rs5
-rw-r--r--src/librustc/ty/adjustment.rs4
-rw-r--r--src/librustc_back/target/mod.rs1
-rw-r--r--src/librustc_back/target/sparcv9_sun_solaris.rs35
-rw-r--r--src/librustc_const_eval/_match.rs92
-rw-r--r--src/librustc_const_eval/check_match.rs34
-rw-r--r--src/librustc_incremental/calculate_svh/svh_visitor.rs9
-rw-r--r--src/librustc_incremental/persist/data.rs5
-rw-r--r--src/librustc_incremental/persist/load.rs12
-rw-r--r--src/librustc_incremental/persist/preds/mod.rs21
-rw-r--r--src/librustc_incremental/persist/save.rs7
-rw-r--r--src/librustc_metadata/creader.rs14
-rw-r--r--src/librustc_metadata/decoder.rs21
-rw-r--r--src/librustc_mir/build/expr/as_lvalue.rs1
-rw-r--r--src/librustc_mir/build/expr/as_rvalue.rs4
-rw-r--r--src/librustc_mir/build/expr/category.rs1
-rw-r--r--src/librustc_mir/build/expr/into.rs1
-rw-r--r--src/librustc_mir/build/scope.rs22
-rw-r--r--src/librustc_mir/hair/cx/expr.rs26
-rw-r--r--src/librustc_mir/hair/cx/mod.rs9
-rw-r--r--src/librustc_mir/hair/mod.rs7
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs1
-rw-r--r--src/librustc_passes/consts.rs1
-rw-r--r--src/librustc_passes/diagnostics.rs16
-rw-r--r--src/librustc_passes/loops.rs49
-rw-r--r--src/librustc_passes/static_recursion.rs24
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs3
-rw-r--r--src/librustc_resolve/lib.rs41
-rw-r--r--src/librustc_resolve/macros.rs60
-rw-r--r--src/librustc_save_analysis/dump_visitor.rs2
-rw-r--r--src/librustc_trans/abi.rs4
-rw-r--r--src/librustc_trans/base.rs17
-rw-r--r--src/librustc_trans/builder.rs9
-rw-r--r--src/librustc_trans/collector.rs32
-rw-r--r--src/librustc_trans/glue.rs10
-rw-r--r--src/librustc_trans/meth.rs8
-rw-r--r--src/librustc_trans/mir/constant.rs23
-rw-r--r--src/librustc_trans/mir/rvalue.rs23
-rw-r--r--src/librustc_typeck/check/coercion.rs65
-rw-r--r--src/librustc_typeck/check/mod.rs19
-rw-r--r--src/librustc_typeck/check/writeback.rs4
-rw-r--r--src/librustdoc/test.rs12
-rw-r--r--src/librustdoc/visit_ast.rs2
-rw-r--r--src/libstd/build.rs4
-rw-r--r--src/libstd/collections/hash/map.rs34
-rw-r--r--src/libstd/panic.rs2
-rw-r--r--src/libstd/sys/redox/mod.rs2
-rw-r--r--src/libstd/sys/redox/net/tcp.rs4
-rw-r--r--src/libstd/sys/redox/net/udp.rs8
-rw-r--r--src/libstd/sys/unix/fs.rs27
-rw-r--r--src/libstd/sys/unix/os.rs2
-rw-r--r--src/libstd/sys/unix/process/magenta.rs2
-rw-r--r--src/libstd/sys/unix/process/process_fuchsia.rs4
-rw-r--r--src/libsyntax/ext/base.rs2
-rw-r--r--src/libsyntax/feature_gate.rs12
-rw-r--r--src/test/COMPILER_TESTS.md (renamed from COMPILER_TESTS.md)0
-rw-r--r--src/test/codegen/function-arguments.rs4
-rw-r--r--src/test/compile-fail-fulldeps/proc-macro/resolve-error.rs29
-rw-r--r--src/test/compile-fail/asm-bad-clobber.rs1
-rw-r--r--src/test/compile-fail/asm-in-bad-modifier.rs1
-rw-r--r--src/test/compile-fail/asm-misplaced-option.rs1
-rw-r--r--src/test/compile-fail/asm-out-assign-imm.rs1
-rw-r--r--src/test/compile-fail/asm-out-no-modifier.rs1
-rw-r--r--src/test/compile-fail/asm-out-read-uninit.rs1
-rw-r--r--src/test/compile-fail/closure-no-fn.rs24
-rw-r--r--src/test/compile-fail/default_ty_param_conflict.rs2
-rw-r--r--src/test/compile-fail/default_ty_param_conflict_cross_crate.rs2
-rw-r--r--src/test/compile-fail/feature-gate-closure_to_fn_coercion.rs45
-rw-r--r--src/test/compile-fail/feature-gate-static_recursion.rs49
-rw-r--r--src/test/compile-fail/issue-3008-2.rs2
-rw-r--r--src/test/compile-fail/issue-35869.rs4
-rw-r--r--src/test/compile-fail/issue-37131.rs4
-rw-r--r--src/test/compile-fail/issue-37576.rs55
-rw-r--r--src/test/compile-fail/match-privately-empty.rs30
-rw-r--r--src/test/compile-fail/resolve-label.rs3
-rw-r--r--src/test/compile-fail/uninhabited-matches-feature-gated.rs10
-rw-r--r--src/test/incremental/issue-39828/auxiliary/generic.rs18
-rw-r--r--src/test/incremental/issue-39828/issue-39828.rs22
-rw-r--r--src/test/parse-fail/range_inclusive_gate.rs2
-rw-r--r--src/test/run-make/graphviz-flowgraph/f10.dot-expected.dot16
-rw-r--r--src/test/run-make/graphviz-flowgraph/f23.dot-expected.dot48
-rw-r--r--src/test/run-pass/auxiliary/clibrary.rs (renamed from src/test/compile-fail/static-recursion-gate.rs)11
-rw-r--r--src/test/run-pass/auxiliary/issue_39823.rs17
-rw-r--r--src/test/run-pass/closure-to-fn-coercion.rs41
-rw-r--r--src/test/run-pass/issue-2063-resource.rs2
-rw-r--r--src/test/run-pass/issue-2063.rs2
-rw-r--r--src/test/run-pass/issue-38972.rs25
-rw-r--r--src/test/run-pass/issue-39823.rs34
-rw-r--r--src/test/run-pass/iter-sum-overflow-overflow-checks.rs35
-rw-r--r--src/test/run-pass/lib-defaults.rs23
-rw-r--r--src/test/run-pass/loop-break-value.rs10
-rw-r--r--src/test/run-pass/panic-safe.rs5
-rw-r--r--src/test/run-pass/static-recursive.rs2
-rw-r--r--src/test/ui/mismatched_types/E0053.stderr3
-rw-r--r--src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr3
-rw-r--r--src/tools/build-manifest/src/main.rs10
-rw-r--r--src/tools/compiletest/src/runtest.rs17
-rw-r--r--src/tools/tidy/src/features.rs6
119 files changed, 1519 insertions, 535 deletions
diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs
index 62e476bd737..a996240f616 100644
--- a/src/bootstrap/bin/rustc.rs
+++ b/src/bootstrap/bin/rustc.rs
@@ -68,6 +68,7 @@ fn main() {
     };
     let stage = env::var("RUSTC_STAGE").expect("RUSTC_STAGE was not set");
     let sysroot = env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set");
+    let mut on_fail = env::var_os("RUSTC_ON_FAIL").map(|of| Command::new(of));
 
     let rustc = env::var_os(rustc).unwrap_or_else(|| panic!("{:?} was not set", rustc));
     let libdir = env::var_os(libdir).unwrap_or_else(|| panic!("{:?} was not set", libdir));
@@ -217,9 +218,20 @@ fn main() {
     }
 
     // Actually run the compiler!
-    std::process::exit(match exec_cmd(&mut cmd) {
-        Ok(s) => s.code().unwrap_or(0xfe),
-        Err(e) => panic!("\n\nfailed to run {:?}: {}\n\n", cmd, e),
+    std::process::exit(if let Some(ref mut on_fail) = on_fail {
+        match cmd.status() {
+            Ok(s) if s.success() => 0,
+            _ => {
+                println!("\nDid not run successfully:\n{:?}\n-------------", cmd);
+                exec_cmd(on_fail).expect("could not run the backup command");
+                1
+            }
+        }
+    } else {
+        std::process::exit(match exec_cmd(&mut cmd) {
+            Ok(s) => s.code().unwrap_or(0xfe),
+            Err(e) => panic!("\n\nfailed to run {:?}: {}\n\n", cmd, e),
+        })
     })
 }
 
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 6b1b8ddf56f..c1ee0c29ac9 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -355,8 +355,12 @@ class RustBuild(object):
         env = os.environ.copy()
         env["CARGO_TARGET_DIR"] = build_dir
         env["RUSTC"] = self.rustc()
-        env["LD_LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib")
-        env["DYLD_LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib")
+        env["LD_LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib") + \
+                                 (os.pathsep + env["LD_LIBRARY_PATH"]) \
+                                 if "LD_LIBRARY_PATH" in env else ""
+        env["DYLD_LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib") + \
+                                   (os.pathsep + env["DYLD_LIBRARY_PATH"]) \
+                                   if "DYLD_LIBRARY_PATH" in env else ""
         env["PATH"] = os.path.join(self.bin_root(), "bin") + \
                       os.pathsep + env["PATH"]
         if not os.path.isfile(self.cargo()):
@@ -485,6 +489,8 @@ class RustBuild(object):
             ostype += 'abi64'
         elif cputype in {'powerpc', 'ppc', 'ppc64'}:
             cputype = 'powerpc'
+        elif cputype == 'sparcv9':
+            pass
         elif cputype in {'amd64', 'x86_64', 'x86-64', 'x64'}:
             cputype = 'x86_64'
         else:
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index c5bbfd89b27..b55f3d710ca 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -28,6 +28,7 @@ use step;
 /// Deserialized version of all flags for this compile.
 pub struct Flags {
     pub verbose: usize, // verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose
+    pub on_fail: Option<String>,
     pub stage: Option<u32>,
     pub keep_stage: Option<u32>,
     pub build: String,
@@ -81,6 +82,7 @@ impl Flags {
         opts.optopt("", "build", "build target of the stage0 compiler", "BUILD");
         opts.optmulti("", "host", "host targets to build", "HOST");
         opts.optmulti("", "target", "target targets to build", "TARGET");
+        opts.optopt("", "on-fail", "command to run on failure", "CMD");
         opts.optopt("", "stage", "stage to build", "N");
         opts.optopt("", "keep-stage", "stage to keep without recompiling", "N");
         opts.optopt("", "src", "path to the root of the rust checkout", "DIR");
@@ -283,6 +285,7 @@ To learn more about a subcommand, run `./x.py <command> -h`
         Flags {
             verbose: m.opt_count("v"),
             stage: stage,
+            on_fail: m.opt_str("on-fail"),
             keep_stage: m.opt_str("keep-stage").map(|j| j.parse().unwrap()),
             build: m.opt_str("build").unwrap_or_else(|| {
                 env::var("BUILD").unwrap()
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 7bd611eb53e..2b34142b3b0 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -499,6 +499,10 @@ impl Build {
             cargo.env("RUSTC_INCREMENTAL", incr_dir);
         }
 
+        if let Some(ref on_fail) = self.flags.on_fail {
+            cargo.env("RUSTC_ON_FAIL", on_fail);
+        }
+
         let verbose = cmp::max(self.config.verbose, self.flags.verbose);
         cargo.env("RUSTC_VERBOSE", format!("{}", verbose));
 
@@ -828,17 +832,6 @@ impl Build {
         if target.contains("apple-darwin") {
             base.push("-stdlib=libc++".into());
         }
-        // This is a hack, because newer binutils broke things on some vms/distros
-        // (i.e., linking against unknown relocs disabled by the following flag)
-        // See: https://github.com/rust-lang/rust/issues/34978
-        match target {
-            "i586-unknown-linux-gnu" |
-            "i686-unknown-linux-musl" |
-            "x86_64-unknown-linux-musl" => {
-                base.push("-Wa,-mrelax-relocations=no".into());
-            },
-            _ => {},
-        }
         return base
     }
 
diff --git a/src/ci/docker/linux-tested-targets/Dockerfile b/src/ci/docker/linux-tested-targets/Dockerfile
index 9906b162cc2..e935226e361 100644
--- a/src/ci/docker/linux-tested-targets/Dockerfile
+++ b/src/ci/docker/linux-tested-targets/Dockerfile
@@ -34,6 +34,14 @@ ENV RUST_CONFIGURE_ARGS \
       --musl-root-x86_64=/musl-x86_64 \
       --musl-root-i686=/musl-i686
 
+# Newer binutils broke things on some vms/distros (i.e., linking against
+# unknown relocs disabled by the following flag), so we need to go out of our
+# way to produce "super compatible" binaries.
+#
+# See: https://github.com/rust-lang/rust/issues/34978
+ENV CFLAGS_i686_unknown_linux_gnu=-Wa,-mrelax-relocations=no \
+    CFLAGS_x86_64_unknown_linux_gnu=-Wa,-mrelax-relocations=no
+
 ENV SCRIPT \
       python2.7 ../x.py test \
           --target x86_64-unknown-linux-musl \
diff --git a/src/ci/docker/linux-tested-targets/build-musl.sh b/src/ci/docker/linux-tested-targets/build-musl.sh
index 260dc11509f..ce62c392241 100644
--- a/src/ci/docker/linux-tested-targets/build-musl.sh
+++ b/src/ci/docker/linux-tested-targets/build-musl.sh
@@ -11,7 +11,10 @@
 
 set -ex
 
-export CFLAGS="-fPIC"
+# We need to mitigate rust-lang/rust#34978 when compiling musl itself as well
+export CFLAGS="-fPIC -Wa,-mrelax-relocations=no"
+export CXXFLAGS="-Wa,-mrelax-relocations=no"
+
 MUSL=musl-1.1.14
 curl https://www.musl-libc.org/releases/$MUSL.tar.gz | tar xzf -
 cd $MUSL
diff --git a/src/doc/nomicon/src/phantom-data.md b/src/doc/nomicon/src/phantom-data.md
index 72fa2e2a777..32539c2d01f 100644
--- a/src/doc/nomicon/src/phantom-data.md
+++ b/src/doc/nomicon/src/phantom-data.md
@@ -82,5 +82,23 @@ standard library made a utility for itself called `Unique<T>` which:
 
 * wraps a `*const T` for variance
 * includes a `PhantomData<T>`
-* auto-derives Send/Sync as if T was contained
-* marks the pointer as NonZero for the null-pointer optimization
+* auto-derives `Send`/`Sync` as if T was contained
+* marks the pointer as `NonZero` for the null-pointer optimization
+
+## Table of `PhantomData` patterns
+
+Here’s a table of all the wonderful ways `PhantomData` could be used:
+
+| Phantom type                | `'a`      | `T`                       |
+|-----------------------------|-----------|---------------------------|
+| `PhantomData<T>`            | -         | variant (with drop check) |
+| `PhantomData<&'a T>`        | variant   | variant                   |
+| `PhantomData<&'a mut T>`    | variant   | invariant                 |
+| `PhantomData<*const T>`     | -         | variant                   |
+| `PhantomData<*mut T>`       | -         | invariant                 |
+| `PhantomData<fn(T)>`        | -         | contravariant (*)         |
+| `PhantomData<fn() -> T>`    | -         | variant                   |
+| `PhantomData<fn(T) -> T>`   | -         | invariant                 |
+| `PhantomData<Cell<&'a ()>>` | invariant | -                         |
+
+(*) If contravariance gets scrapped, this would be invariant.
diff --git a/src/libcompiler_builtins/build.rs b/src/libcompiler_builtins/build.rs
index 5360bbdeacd..16ecf882566 100644
--- a/src/libcompiler_builtins/build.rs
+++ b/src/libcompiler_builtins/build.rs
@@ -92,7 +92,15 @@ fn main() {
         // compiler-rt's build system already
         cfg.flag("-fno-builtin");
         cfg.flag("-fvisibility=hidden");
-        cfg.flag("-fomit-frame-pointer");
+        // Accepted practice on Solaris is to never omit frame pointer so that
+        // system observability tools work as expected.  In addition, at least
+        // on Solaris, -fomit-frame-pointer on sparcv9 appears to generate
+        // references to data outside of the current stack frame.  A search of
+        // the gcc bug database provides a variety of issues surrounding
+        // -fomit-frame-pointer on non-x86 platforms.
+        if !target.contains("solaris") && !target.contains("sparc") {
+            cfg.flag("-fomit-frame-pointer");
+        }
         cfg.flag("-ffreestanding");
         cfg.define("VISIBILITY_HIDDEN", None);
     }
diff --git a/src/liblibc b/src/liblibc
-Subproject 7a3754f2bb5e65eb39adacb189c362617303217
+Subproject 64d954c6a76e896fbf7ed5c17e77c40e388abe8
diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs
index 59505933289..122543aee40 100644
--- a/src/librustc/cfg/construct.rs
+++ b/src/librustc/cfg/construct.rs
@@ -220,15 +220,24 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
                 // Note that `break` and `continue` statements
                 // may cause additional edges.
 
-                // Is the condition considered part of the loop?
                 let loopback = self.add_dummy_node(&[pred]);              // 1
-                let cond_exit = self.expr(&cond, loopback);             // 2
-                let expr_exit = self.add_ast_node(expr.id, &[cond_exit]); // 3
+
+                // Create expr_exit without pred (cond_exit)
+                let expr_exit = self.add_ast_node(expr.id, &[]);         // 3
+
+                // The LoopScope needs to be on the loop_scopes stack while evaluating the
+                // condition and the body of the loop (both can break out of the loop)
                 self.loop_scopes.push(LoopScope {
                     loop_id: expr.id,
                     continue_index: loopback,
                     break_index: expr_exit
                 });
+
+                let cond_exit = self.expr(&cond, loopback);             // 2
+
+                // Add pred (cond_exit) to expr_exit
+                self.add_contained_edge(cond_exit, expr_exit);
+
                 let body_exit = self.block(&body, cond_exit);          // 4
                 self.add_contained_edge(body_exit, loopback);            // 5
                 self.loop_scopes.pop();
@@ -294,17 +303,17 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
                 self.add_unreachable_node()
             }
 
-            hir::ExprBreak(label, ref opt_expr) => {
+            hir::ExprBreak(destination, ref opt_expr) => {
                 let v = self.opt_expr(opt_expr, pred);
-                let loop_scope = self.find_scope(expr, label);
+                let loop_scope = self.find_scope(expr, destination);
                 let b = self.add_ast_node(expr.id, &[v]);
                 self.add_exiting_edge(expr, b,
                                       loop_scope, loop_scope.break_index);
                 self.add_unreachable_node()
             }
 
-            hir::ExprAgain(label) => {
-                let loop_scope = self.find_scope(expr, label);
+            hir::ExprAgain(destination) => {
+                let loop_scope = self.find_scope(expr, destination);
                 let a = self.add_ast_node(expr.id, &[pred]);
                 self.add_exiting_edge(expr, a,
                                       loop_scope, loop_scope.continue_index);
@@ -579,17 +588,18 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
 
     fn find_scope(&self,
                   expr: &hir::Expr,
-                  label: Option<hir::Label>) -> LoopScope {
-        match label {
-            None => *self.loop_scopes.last().unwrap(),
-            Some(label) => {
+                  destination: hir::Destination) -> LoopScope {
+
+        match destination.loop_id.into() {
+            Ok(loop_id) => {
                 for l in &self.loop_scopes {
-                    if l.loop_id == label.loop_id {
+                    if l.loop_id == loop_id {
                         return *l;
                     }
                 }
-                span_bug!(expr.span, "no loop scope for id {}", label.loop_id);
+                span_bug!(expr.span, "no loop scope for id {}", loop_id);
             }
+            Err(err) => span_bug!(expr.span, "loop scope error: {}",  err)
         }
     }
 }
diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs
index 53b7be74f85..aedb8fef288 100644
--- a/src/librustc/hir/def.rs
+++ b/src/librustc/hir/def.rs
@@ -11,6 +11,7 @@
 use hir::def_id::DefId;
 use util::nodemap::NodeMap;
 use syntax::ast;
+use syntax::ext::base::MacroKind;
 use hir;
 
 #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
@@ -53,7 +54,7 @@ pub enum Def {
     Label(ast::NodeId),
 
     // Macro namespace
-    Macro(DefId),
+    Macro(DefId, MacroKind),
 
     // Both namespaces
     Err,
@@ -141,7 +142,7 @@ impl Def {
             Def::Variant(id) | Def::VariantCtor(id, ..) | Def::Enum(id) | Def::TyAlias(id) |
             Def::AssociatedTy(id) | Def::TyParam(id) | Def::Struct(id) | Def::StructCtor(id, ..) |
             Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) |
-            Def::AssociatedConst(id) | Def::Local(id) | Def::Upvar(id, ..) | Def::Macro(id) => {
+            Def::AssociatedConst(id) | Def::Local(id) | Def::Upvar(id, ..) | Def::Macro(id, ..) => {
                 id
             }
 
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs
index 1df67615069..fd6796ccc0b 100644
--- a/src/librustc/hir/intravisit.rs
+++ b/src/librustc/hir/intravisit.rs
@@ -1006,18 +1006,22 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
         ExprPath(ref qpath) => {
             visitor.visit_qpath(qpath, expression.id, expression.span);
         }
-        ExprBreak(None, ref opt_expr) => {
+        ExprBreak(label, ref opt_expr) => {
+            label.ident.map(|ident| {
+                if let Ok(loop_id) = label.loop_id.into() {
+                    visitor.visit_def_mention(Def::Label(loop_id));
+                }
+                visitor.visit_name(ident.span, ident.node.name);
+            });
             walk_list!(visitor, visit_expr, opt_expr);
         }
-        ExprBreak(Some(label), ref opt_expr) => {
-            visitor.visit_def_mention(Def::Label(label.loop_id));
-            visitor.visit_name(label.span, label.name);
-            walk_list!(visitor, visit_expr, opt_expr);
-        }
-        ExprAgain(None) => {}
-        ExprAgain(Some(label)) => {
-            visitor.visit_def_mention(Def::Label(label.loop_id));
-            visitor.visit_name(label.span, label.name);
+        ExprAgain(label) => {
+            label.ident.map(|ident| {
+                if let Ok(loop_id) = label.loop_id.into() {
+                    visitor.visit_def_mention(Def::Label(loop_id));
+                }
+                visitor.visit_name(ident.span, ident.node.name);
+            });
         }
         ExprRet(ref optional_expression) => {
             walk_list!(visitor, visit_expr, optional_expression);
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index c87ce6505fc..8572119e989 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -50,6 +50,7 @@ use util::nodemap::{DefIdMap, NodeMap, FxHashMap};
 
 use std::collections::BTreeMap;
 use std::iter;
+use std::mem;
 
 use syntax::attr;
 use syntax::ast::*;
@@ -79,6 +80,9 @@ pub struct LoweringContext<'a> {
     impl_items: BTreeMap<hir::ImplItemId, hir::ImplItem>,
     bodies: FxHashMap<hir::BodyId, hir::Body>,
 
+    loop_scopes: Vec<NodeId>,
+    is_in_loop_condition: bool,
+
     type_def_lifetime_params: DefIdMap<usize>,
 }
 
@@ -112,6 +116,8 @@ pub fn lower_crate(sess: &Session,
         trait_items: BTreeMap::new(),
         impl_items: BTreeMap::new(),
         bodies: FxHashMap(),
+        loop_scopes: Vec::new(),
+        is_in_loop_condition: false,
         type_def_lifetime_params: DefIdMap(),
     }.lower_crate(krate)
 }
@@ -244,6 +250,55 @@ impl<'a> LoweringContext<'a> {
         span
     }
 
+    fn with_loop_scope<T, F>(&mut self, loop_id: NodeId, f: F) -> T
+        where F: FnOnce(&mut LoweringContext) -> T
+    {
+        // We're no longer in the base loop's condition; we're in another loop.
+        let was_in_loop_condition = self.is_in_loop_condition;
+        self.is_in_loop_condition = false;
+
+        let len = self.loop_scopes.len();
+        self.loop_scopes.push(loop_id);
+
+        let result = f(self);
+        assert_eq!(len + 1, self.loop_scopes.len(),
+            "Loop scopes should be added and removed in stack order");
+
+        self.loop_scopes.pop().unwrap();
+
+        self.is_in_loop_condition = was_in_loop_condition;
+
+        result
+    }
+
+    fn with_loop_condition_scope<T, F>(&mut self, f: F) -> T
+        where F: FnOnce(&mut LoweringContext) -> T
+    {
+        let was_in_loop_condition = self.is_in_loop_condition;
+        self.is_in_loop_condition = true;
+
+        let result = f(self);
+
+        self.is_in_loop_condition = was_in_loop_condition;
+
+        result
+    }
+
+    fn with_new_loop_scopes<T, F>(&mut self, f: F) -> T
+        where F: FnOnce(&mut LoweringContext) -> T
+    {
+        let was_in_loop_condition = self.is_in_loop_condition;
+        self.is_in_loop_condition = false;
+
+        let loop_scopes = mem::replace(&mut self.loop_scopes, Vec::new());
+        let result = f(self);
+        mem::replace(&mut self.loop_scopes, loop_scopes);
+
+        self.is_in_loop_condition = was_in_loop_condition;
+
+        result
+    }
+
     fn with_parent_def<T, F>(&mut self, parent_id: NodeId, f: F) -> T
         where F: FnOnce(&mut LoweringContext) -> T
     {
@@ -271,17 +326,24 @@ impl<'a> LoweringContext<'a> {
         o_id.map(|sp_ident| respan(sp_ident.span, sp_ident.node.name))
     }
 
-    fn lower_label(&mut self, id: NodeId, label: Option<Spanned<Ident>>) -> Option<hir::Label> {
-        label.map(|sp_ident| {
-            hir::Label {
-                span: sp_ident.span,
-                name: sp_ident.node.name,
-                loop_id: match self.expect_full_def(id) {
-                    Def::Label(loop_id) => loop_id,
-                    _ => DUMMY_NODE_ID
+    fn lower_destination(&mut self, destination: Option<(NodeId, Spanned<Ident>)>)
+        -> hir::Destination
+    {
+        match destination {
+            Some((id, label_ident)) => hir::Destination {
+                ident: Some(label_ident),
+                loop_id: if let Def::Label(loop_id) = self.expect_full_def(id) {
+                    hir::LoopIdResult::Ok(loop_id)
+                } else {
+                    hir::LoopIdResult::Err(hir::LoopIdError::UnresolvedLabel)
                 }
+            },
+            None => hir::Destination {
+                ident: None,
+                loop_id: self.loop_scopes.last().map(|innermost_loop_id| Ok(*innermost_loop_id))
+                            .unwrap_or(Err(hir::LoopIdError::OutsideLoopScope)).into()
             }
-        })
+        }
     }
 
     fn lower_attrs(&mut self, attrs: &Vec<Attribute>) -> hir::HirVec<Attribute> {
@@ -992,15 +1054,17 @@ impl<'a> LoweringContext<'a> {
                                self.record_body(value, None))
             }
             ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => {
-                let body = self.lower_block(body);
-                let body = self.expr_block(body, ThinVec::new());
-                let body_id = self.record_body(body, Some(decl));
-                hir::ItemFn(self.lower_fn_decl(decl),
-                            self.lower_unsafety(unsafety),
-                            self.lower_constness(constness),
-                            abi,
-                            self.lower_generics(generics),
-                            body_id)
+                self.with_new_loop_scopes(|this| {
+                    let body = this.lower_block(body);
+                    let body = this.expr_block(body, ThinVec::new());
+                    let body_id = this.record_body(body, Some(decl));
+                    hir::ItemFn(this.lower_fn_decl(decl),
+                                              this.lower_unsafety(unsafety),
+                                              this.lower_constness(constness),
+                                              abi,
+                                              this.lower_generics(generics),
+                                              body_id)
+                })
             }
             ItemKind::Mod(ref m) => hir::ItemMod(self.lower_mod(m)),
             ItemKind::ForeignMod(ref nm) => hir::ItemForeignMod(self.lower_foreign_mod(nm)),
@@ -1562,13 +1626,17 @@ impl<'a> LoweringContext<'a> {
                     hir::ExprIf(P(self.lower_expr(cond)), self.lower_block(blk), else_opt)
                 }
                 ExprKind::While(ref cond, ref body, opt_ident) => {
-                    hir::ExprWhile(P(self.lower_expr(cond)), self.lower_block(body),
-                                   self.lower_opt_sp_ident(opt_ident))
+                    self.with_loop_scope(e.id, |this|
+                        hir::ExprWhile(
+                            this.with_loop_condition_scope(|this| P(this.lower_expr(cond))),
+                            this.lower_block(body),
+                            this.lower_opt_sp_ident(opt_ident)))
                 }
                 ExprKind::Loop(ref body, opt_ident) => {
-                    hir::ExprLoop(self.lower_block(body),
-                                  self.lower_opt_sp_ident(opt_ident),
-                                  hir::LoopSource::Loop)
+                    self.with_loop_scope(e.id, |this|
+                        hir::ExprLoop(this.lower_block(body),
+                                      this.lower_opt_sp_ident(opt_ident),
+                                      hir::LoopSource::Loop))
                 }
                 ExprKind::Match(ref expr, ref arms) => {
                     hir::ExprMatch(P(self.lower_expr(expr)),
@@ -1576,12 +1644,14 @@ impl<'a> LoweringContext<'a> {
                                    hir::MatchSource::Normal)
                 }
                 ExprKind::Closure(capture_clause, ref decl, ref body, fn_decl_span) => {
-                    self.with_parent_def(e.id, |this| {
-                        let expr = this.lower_expr(body);
-                        hir::ExprClosure(this.lower_capture_clause(capture_clause),
-                                         this.lower_fn_decl(decl),
-                                         this.record_body(expr, Some(decl)),
-                                         fn_decl_span)
+                    self.with_new_loop_scopes(|this| {
+                        this.with_parent_def(e.id, |this| {
+                            let expr = this.lower_expr(body);
+                            hir::ExprClosure(this.lower_capture_clause(capture_clause),
+                                             this.lower_fn_decl(decl),
+                                             this.record_body(expr, Some(decl)),
+                                             fn_decl_span)
+                        })
                     })
                 }
                 ExprKind::Block(ref blk) => hir::ExprBlock(self.lower_block(blk)),
@@ -1660,10 +1730,29 @@ impl<'a> LoweringContext<'a> {
                     hir::ExprPath(self.lower_qpath(e.id, qself, path, ParamMode::Optional))
                 }
                 ExprKind::Break(opt_ident, ref opt_expr) => {
-                    hir::ExprBreak(self.lower_label(e.id, opt_ident),
-                                   opt_expr.as_ref().map(|x| P(self.lower_expr(x))))
+                    let label_result = if self.is_in_loop_condition && opt_ident.is_none() {
+                        hir::Destination {
+                            ident: opt_ident,
+                            loop_id: Err(hir::LoopIdError::UnlabeledCfInWhileCondition).into(),
+                        }
+                    } else {
+                        self.lower_destination(opt_ident.map(|ident| (e.id, ident)))
+                    };
+                    hir::ExprBreak(
+                            label_result,
+                            opt_expr.as_ref().map(|x| P(self.lower_expr(x))))
                 }
-                ExprKind::Continue(opt_ident) => hir::ExprAgain(self.lower_label(e.id, opt_ident)),
+                ExprKind::Continue(opt_ident) =>
+                    hir::ExprAgain(
+                        if self.is_in_loop_condition && opt_ident.is_none() {
+                            hir::Destination {
+                                ident: opt_ident,
+                                loop_id: Err(
+                                    hir::LoopIdError::UnlabeledCfInWhileCondition).into(),
+                            }
+                        } else {
+                            self.lower_destination(opt_ident.map( |ident| (e.id, ident)))
+                        }),
                 ExprKind::Ret(ref e) => hir::ExprRet(e.as_ref().map(|x| P(self.lower_expr(x)))),
                 ExprKind::InlineAsm(ref asm) => {
                     let hir_asm = hir::InlineAsm {
@@ -1804,9 +1893,16 @@ impl<'a> LoweringContext<'a> {
                     //     }
                     //   }
 
+                    // Note that the block AND the condition are evaluated in the loop scope.
+                    // This is done to allow `break` from inside the condition of the loop.
+                    let (body, break_expr, sub_expr) = self.with_loop_scope(e.id, |this| (
+                        this.lower_block(body),
+                        this.expr_break(e.span, ThinVec::new()),
+                        this.with_loop_condition_scope(|this| P(this.lower_expr(sub_expr))),
+                    ));
+
                     // `<pat> => <body>`
                     let pat_arm = {
-                        let body = self.lower_block(body);
                         let body_expr = P(self.expr_block(body, ThinVec::new()));
                         let pat = self.lower_pat(pat);
                         self.arm(hir_vec![pat], body_expr)
@@ -1815,13 +1911,11 @@ impl<'a> LoweringContext<'a> {
                     // `_ => break`
                     let break_arm = {
                         let pat_under = self.pat_wild(e.span);
-                        let break_expr = self.expr_break(e.span, ThinVec::new());
                         self.arm(hir_vec![pat_under], break_expr)
                     };
 
                     // `match <sub_expr> { ... }`
                     let arms = hir_vec![pat_arm, break_arm];
-                    let sub_expr = P(self.lower_expr(sub_expr));
                     let match_expr = self.expr(e.span,
                                                hir::ExprMatch(sub_expr,
                                                               arms,
@@ -1863,7 +1957,7 @@ impl<'a> LoweringContext<'a> {
 
                     // `::std::option::Option::Some(<pat>) => <body>`
                     let pat_arm = {
-                        let body_block = self.lower_block(body);
+                        let body_block = self.with_loop_scope(e.id, |this| this.lower_block(body));
                         let body_expr = P(self.expr_block(body_block, ThinVec::new()));
                         let pat = self.lower_pat(pat);
                         let some_pat = self.pat_some(e.span, pat);
@@ -1873,7 +1967,8 @@ impl<'a> LoweringContext<'a> {
 
                     // `::std::option::Option::None => break`
                     let break_arm = {
-                        let break_expr = self.expr_break(e.span, ThinVec::new());
+                        let break_expr = self.with_loop_scope(e.id, |this|
+                            this.expr_break(e.span, ThinVec::new()));
                         let pat = self.pat_none(e.span);
                         self.arm(hir_vec![pat], break_expr)
                     };
@@ -2151,7 +2246,8 @@ impl<'a> LoweringContext<'a> {
     }
 
     fn expr_break(&mut self, span: Span, attrs: ThinVec<Attribute>) -> P<hir::Expr> {
-        P(self.expr(span, hir::ExprBreak(None, None), attrs))
+        let expr_break = hir::ExprBreak(self.lower_destination(None), None);
+        P(self.expr(span, expr_break, attrs))
     }
 
     fn expr_call(&mut self, span: Span, e: P<hir::Expr>, args: hir::HirVec<hir::Expr>)
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 4ebe416e1bf..e8c5f2447cd 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -36,7 +36,7 @@ use util::nodemap::{NodeMap, FxHashMap, FxHashSet};
 use syntax_pos::{Span, ExpnId, DUMMY_SP};
 use syntax::codemap::{self, Spanned};
 use syntax::abi::Abi;
-use syntax::ast::{Name, NodeId, DUMMY_NODE_ID, AsmDialect};
+use syntax::ast::{Ident, Name, NodeId, DUMMY_NODE_ID, AsmDialect};
 use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, MetaItem};
 use syntax::ptr::P;
 use syntax::symbol::{Symbol, keywords};
@@ -959,9 +959,9 @@ pub enum Expr_ {
     /// A referencing operation (`&a` or `&mut a`)
     ExprAddrOf(Mutability, P<Expr>),
     /// A `break`, with an optional label to break
-    ExprBreak(Option<Label>, Option<P<Expr>>),
+    ExprBreak(Destination, Option<P<Expr>>),
     /// A `continue`, with an optional label
-    ExprAgain(Option<Label>),
+    ExprAgain(Destination),
     /// A `return`, with an optional value to be returned
     ExprRet(Option<P<Expr>>),
 
@@ -1030,12 +1030,56 @@ pub enum LoopSource {
     ForLoop,
 }
 
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
+pub enum LoopIdError {
+    OutsideLoopScope,
+    UnlabeledCfInWhileCondition,
+    UnresolvedLabel,
+}
+
+impl fmt::Display for LoopIdError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(match *self {
+            LoopIdError::OutsideLoopScope => "not inside loop scope",
+            LoopIdError::UnlabeledCfInWhileCondition =>
+                "unlabeled control flow (break or continue) in while condition",
+            LoopIdError::UnresolvedLabel => "label not found",
+        }, f)
+    }
+}
 
+// FIXME(cramertj) this should use `Result` once master compiles w/ a vesion of Rust where
+// `Result` implements `Encodable`/`Decodable`
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
-pub struct Label {
-    pub span: Span,
-    pub name: Name,
-    pub loop_id: NodeId
+pub enum LoopIdResult {
+    Ok(NodeId),
+    Err(LoopIdError),
+}
+impl Into<Result<NodeId, LoopIdError>> for LoopIdResult {
+    fn into(self) -> Result<NodeId, LoopIdError> {
+        match self {
+            LoopIdResult::Ok(ok) => Ok(ok),
+            LoopIdResult::Err(err) => Err(err),
+        }
+    }
+}
+impl From<Result<NodeId, LoopIdError>> for LoopIdResult {
+    fn from(res: Result<NodeId, LoopIdError>) -> Self {
+        match res {
+            Ok(ok) => LoopIdResult::Ok(ok),
+            Err(err) => LoopIdResult::Err(err),
+        }
+    }
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
+pub struct Destination {
+    // This is `Some(_)` iff there is an explicit user-specified `label
+    pub ident: Option<Spanned<Ident>>,
+
+    // These errors are caught and then reported during the diagnostics pass in
+    // librustc_passes/loops.rs
+    pub loop_id: LoopIdResult,
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs
index e058c48c591..3411de9bb5d 100644
--- a/src/librustc/hir/print.rs
+++ b/src/librustc/hir/print.rs
@@ -1354,11 +1354,11 @@ impl<'a> State<'a> {
             hir::ExprPath(ref qpath) => {
                 self.print_qpath(qpath, true)?
             }
-            hir::ExprBreak(opt_label, ref opt_expr) => {
+            hir::ExprBreak(label, ref opt_expr) => {
                 word(&mut self.s, "break")?;
                 space(&mut self.s)?;
-                if let Some(label) = opt_label {
-                    self.print_name(label.name)?;
+                if let Some(label_ident) = label.ident {
+                    self.print_name(label_ident.node.name)?;
                     space(&mut self.s)?;
                 }
                 if let Some(ref expr) = *opt_expr {
@@ -1366,11 +1366,11 @@ impl<'a> State<'a> {
                     space(&mut self.s)?;
                 }
             }
-            hir::ExprAgain(opt_label) => {
+            hir::ExprAgain(label) => {
                 word(&mut self.s, "continue")?;
                 space(&mut self.s)?;
-                if let Some(label) = opt_label {
-                    self.print_name(label.name)?;
+                if let Some(label_ident) = label.ident {
+                    self.print_name(label_ident.node.name)?;
                     space(&mut self.s)?
                 }
             }
diff --git a/src/librustc/infer/error_reporting.rs b/src/librustc/infer/error_reporting.rs
index 9295fb2ee32..f48ff87689f 100644
--- a/src/librustc/infer/error_reporting.rs
+++ b/src/librustc/infer/error_reporting.rs
@@ -379,40 +379,41 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                          values: Option<ValuePairs<'tcx>>,
                          terr: &TypeError<'tcx>)
     {
-        let expected_found = match values {
-            None => None,
-            Some(values) => match self.values_str(&values) {
-                Some((expected, found)) => Some((expected, found)),
-                None => {
-                    // Derived error. Cancel the emitter.
-                    self.tcx.sess.diagnostic().cancel(diag);
-                    return
-                }
+        let (expected_found, is_simple_error) = match values {
+            None => (None, false),
+            Some(values) => {
+                let is_simple_error = match values {
+                    ValuePairs::Types(exp_found) => {
+                        exp_found.expected.is_primitive() && exp_found.found.is_primitive()
+                    }
+                    _ => false,
+                };
+                let vals = match self.values_str(&values) {
+                    Some((expected, found)) => Some((expected, found)),
+                    None => {
+                        // Derived error. Cancel the emitter.
+                        self.tcx.sess.diagnostic().cancel(diag);
+                        return
+                    }
+                };
+                (vals, is_simple_error)
             }
         };
 
         let span = cause.span;
 
         if let Some((expected, found)) = expected_found {
-            let is_simple_error = if let &TypeError::Sorts(ref values) = terr {
-                values.expected.is_primitive() && values.found.is_primitive()
-            } else {
-                false
-            };
-
-            if !is_simple_error {
-                if expected == found {
-                    if let &TypeError::Sorts(ref values) = terr {
-                        diag.note_expected_found_extra(
-                            &"type", &expected, &found,
-                            &format!(" ({})", values.expected.sort_string(self.tcx)),
-                            &format!(" ({})", values.found.sort_string(self.tcx)));
-                    } else {
-                        diag.note_expected_found(&"type", &expected, &found);
-                    }
-                } else {
+            match (terr, is_simple_error, expected == found) {
+                (&TypeError::Sorts(ref values), false,  true) => {
+                    diag.note_expected_found_extra(
+                        &"type", &expected, &found,
+                        &format!(" ({})", values.expected.sort_string(self.tcx)),
+                        &format!(" ({})", values.found.sort_string(self.tcx)));
+                }
+                (_, false,  _) => {
                     diag.note_expected_found(&"type", &expected, &found);
                 }
+                _ => (),
             }
         }
 
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index 2ca0069560c..a44679b0b3e 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -715,6 +715,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
                 adjustment::Adjust::NeverToAny |
                 adjustment::Adjust::ReifyFnPointer |
                 adjustment::Adjust::UnsafeFnPointer |
+                adjustment::Adjust::ClosureFnPointer |
                 adjustment::Adjust::MutToConstPointer => {
                     // Creating a closure/fn-pointer or unsizing consumes
                     // the input and stores it into the resulting rvalue.
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index 7fa3365694c..b7f7c49d7b0 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -675,23 +675,6 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
         Ok(())
     }
 
-    fn find_loop_scope(&self,
-                       opt_label: Option<hir::Label>,
-                       sp: Span)
-                       -> NodeId {
-        match opt_label {
-            Some(label) => label.loop_id,
-            None => {
-                // Vanilla 'break' or 'continue', so use the enclosing
-                // loop scope
-                if self.loop_scope.is_empty() {
-                    span_bug!(sp, "break outside loop");
-                } else {
-                    *self.loop_scope.last().unwrap()
-                }
-            }
-        }
-    }
 
     #[allow(unused_must_use)]
     fn ln_str(&self, ln: LiveNode) -> String {
@@ -1018,9 +1001,12 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
             self.propagate_through_opt_expr(o_e.as_ref().map(|e| &**e), exit_ln)
           }
 
-          hir::ExprBreak(opt_label, ref opt_expr) => {
+          hir::ExprBreak(label, ref opt_expr) => {
               // Find which label this break jumps to
-              let sc = self.find_loop_scope(opt_label, expr.span);
+              let sc = match label.loop_id.into() {
+                  Ok(loop_id) => loop_id,
+                  Err(err) => span_bug!(expr.span, "loop scope error: {}", err),
+              };
 
               // Now that we know the label we're going to,
               // look it up in the break loop nodes table
@@ -1031,9 +1017,13 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
               }
           }
 
-          hir::ExprAgain(opt_label) => {
+          hir::ExprAgain(label) => {
               // Find which label this expr continues to
-              let sc = self.find_loop_scope(opt_label, expr.span);
+              let sc = match label.loop_id.into() {
+                  Ok(loop_id) => loop_id,
+                  Err(err) => span_bug!(expr.span, "loop scope error: {}", err),
+              };
+
 
               // Now that we know the label we're going to,
               // look it up in the continue loop nodes table
@@ -1297,12 +1287,13 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
         debug!("propagate_through_loop: using id for loop body {} {}",
                expr.id, self.ir.tcx.hir.node_to_pretty_string(body.id));
 
-        let cond_ln = match kind {
-            LoopLoop => ln,
-            WhileLoop(ref cond) => self.propagate_through_expr(&cond, ln),
-        };
-        let body_ln = self.with_loop_nodes(expr.id, succ, ln, |this| {
-            this.propagate_through_block(body, cond_ln)
+        let (cond_ln, body_ln) = self.with_loop_nodes(expr.id, succ, ln, |this| {
+            let cond_ln = match kind {
+                LoopLoop => ln,
+                WhileLoop(ref cond) => this.propagate_through_expr(&cond, ln),
+            };
+            let body_ln = this.propagate_through_block(body, cond_ln);
+            (cond_ln, body_ln)
         });
 
         // repeat until fixed point is reached:
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 627753039ba..b0c85e2ef4c 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -464,6 +464,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
                     adjustment::Adjust::NeverToAny |
                     adjustment::Adjust::ReifyFnPointer |
                     adjustment::Adjust::UnsafeFnPointer |
+                    adjustment::Adjust::ClosureFnPointer |
                     adjustment::Adjust::MutToConstPointer |
                     adjustment::Adjust::DerefRef {..} => {
                         debug!("cat_expr({:?}): {:?}",
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index 3403cf04774..d2a657e35b5 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -1022,6 +1022,9 @@ pub enum CastKind {
     /// Convert unique, zero-sized type for a fn to fn()
     ReifyFnPointer,
 
+    /// Convert non capturing closure to fn()
+    ClosureFnPointer,
+
     /// Convert safe fn() to unsafe fn()
     UnsafeFnPointer,
 
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 24615f2fa69..5fff03dabce 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -51,7 +51,7 @@ pub struct Config {
     pub uint_type: UintTy,
 }
 
-#[derive(Clone)]
+#[derive(Clone, Hash)]
 pub enum Sanitizer {
     Address,
     Leak,
@@ -288,7 +288,7 @@ top_level_options!(
         //            much sense: The search path can stay the same while the
         //            things discovered there might have changed on disk.
         search_paths: SearchPaths [TRACKED],
-        libs: Vec<(String, Option<String>, cstore::NativeLibraryKind)> [TRACKED],
+        libs: Vec<(String, Option<String>, Option<cstore::NativeLibraryKind>)> [TRACKED],
         maybe_sysroot: Option<PathBuf> [TRACKED],
 
         target_triple: String [TRACKED],
@@ -804,6 +804,8 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options,
         "save all temporary output files during compilation"),
     rpath: bool = (false, parse_bool, [UNTRACKED],
         "set rpath values in libs/exes"),
+    overflow_checks: Option<bool> = (None, parse_opt_bool, [TRACKED],
+        "use overflow checks for integer arithmetic"),
     no_prepopulate_passes: bool = (false, parse_bool, [TRACKED],
         "don't pre-populate the pass manager with a list of passes"),
     no_vectorize_loops: bool = (false, parse_bool, [TRACKED],
@@ -970,7 +972,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
           "encode MIR of all functions into the crate metadata"),
     osx_rpath_install_name: bool = (false, parse_bool, [TRACKED],
           "pass `-install_name @rpath/...` to the OSX linker"),
-    sanitizer: Option<Sanitizer> = (None, parse_sanitizer, [UNTRACKED],
+    sanitizer: Option<Sanitizer> = (None, parse_sanitizer, [TRACKED],
                                    "Use a sanitizer"),
 }
 
@@ -1495,18 +1497,18 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
         let mut parts = s.splitn(2, '=');
         let kind = parts.next().unwrap();
         let (name, kind) = match (parts.next(), kind) {
-            (None, name) |
-            (Some(name), "dylib") => (name, cstore::NativeUnknown),
-            (Some(name), "framework") => (name, cstore::NativeFramework),
-            (Some(name), "static") => (name, cstore::NativeStatic),
-            (Some(name), "static-nobundle") => (name, cstore::NativeStaticNobundle),
+            (None, name) => (name, None),
+            (Some(name), "dylib") => (name, Some(cstore::NativeUnknown)),
+            (Some(name), "framework") => (name, Some(cstore::NativeFramework)),
+            (Some(name), "static") => (name, Some(cstore::NativeStatic)),
+            (Some(name), "static-nobundle") => (name, Some(cstore::NativeStaticNobundle)),
             (_, s) => {
                 early_error(error_format, &format!("unknown library kind `{}`, expected \
                                                   one of dylib, framework, or static",
                                                  s));
             }
         };
-        if kind == cstore::NativeStaticNobundle && !nightly_options::is_nightly_build() {
+        if kind == Some(cstore::NativeStaticNobundle) && !nightly_options::is_nightly_build() {
             early_error(error_format, &format!("the library kind 'static-nobundle' is only \
                                                 accepted on the nightly compiler"));
         }
@@ -1728,7 +1730,7 @@ mod dep_tracking {
     use std::path::PathBuf;
     use std::collections::hash_map::DefaultHasher;
     use super::{Passes, CrateType, OptLevel, DebugInfoLevel,
-                OutputTypes, Externs, ErrorOutputType};
+                OutputTypes, Externs, ErrorOutputType, Sanitizer};
     use syntax::feature_gate::UnstableFeatures;
     use rustc_back::PanicStrategy;
 
@@ -1772,6 +1774,7 @@ mod dep_tracking {
     impl_dep_tracking_hash_via_hash!(Option<PanicStrategy>);
     impl_dep_tracking_hash_via_hash!(Option<lint::Level>);
     impl_dep_tracking_hash_via_hash!(Option<PathBuf>);
+    impl_dep_tracking_hash_via_hash!(Option<cstore::NativeLibraryKind>);
     impl_dep_tracking_hash_via_hash!(CrateType);
     impl_dep_tracking_hash_via_hash!(PanicStrategy);
     impl_dep_tracking_hash_via_hash!(Passes);
@@ -1781,12 +1784,14 @@ mod dep_tracking {
     impl_dep_tracking_hash_via_hash!(Externs);
     impl_dep_tracking_hash_via_hash!(OutputTypes);
     impl_dep_tracking_hash_via_hash!(cstore::NativeLibraryKind);
+    impl_dep_tracking_hash_via_hash!(Sanitizer);
+    impl_dep_tracking_hash_via_hash!(Option<Sanitizer>);
 
     impl_dep_tracking_hash_for_sortable_vec_of!(String);
     impl_dep_tracking_hash_for_sortable_vec_of!(CrateType);
     impl_dep_tracking_hash_for_sortable_vec_of!((String, lint::Level));
     impl_dep_tracking_hash_for_sortable_vec_of!((String, Option<String>,
-                                                 cstore::NativeLibraryKind));
+                                                 Option<cstore::NativeLibraryKind>));
     impl DepTrackingHash for SearchPaths {
         fn hash(&self, hasher: &mut DefaultHasher, _: ErrorOutputType) {
             let mut elems: Vec<_> = self
@@ -2230,24 +2235,24 @@ mod tests {
         let mut v4 = super::basic_options();
 
         // Reference
-        v1.libs = vec![(String::from("a"), None, cstore::NativeStatic),
-                       (String::from("b"), None, cstore::NativeFramework),
-                       (String::from("c"), None, cstore::NativeUnknown)];
+        v1.libs = vec![(String::from("a"), None, Some(cstore::NativeStatic)),
+                       (String::from("b"), None, Some(cstore::NativeFramework)),
+                       (String::from("c"), None, Some(cstore::NativeUnknown))];
 
         // Change label
-        v2.libs = vec![(String::from("a"), None, cstore::NativeStatic),
-                       (String::from("X"), None, cstore::NativeFramework),
-                       (String::from("c"), None, cstore::NativeUnknown)];
+        v2.libs = vec![(String::from("a"), None, Some(cstore::NativeStatic)),
+                       (String::from("X"), None, Some(cstore::NativeFramework)),
+                       (String::from("c"), None, Some(cstore::NativeUnknown))];
 
         // Change kind
-        v3.libs = vec![(String::from("a"), None, cstore::NativeStatic),
-                       (String::from("b"), None, cstore::NativeStatic),
-                       (String::from("c"), None, cstore::NativeUnknown)];
+        v3.libs = vec![(String::from("a"), None, Some(cstore::NativeStatic)),
+                       (String::from("b"), None, Some(cstore::NativeStatic)),
+                       (String::from("c"), None, Some(cstore::NativeUnknown))];
 
         // Change new-name
-        v4.libs = vec![(String::from("a"), None, cstore::NativeStatic),
-                       (String::from("b"), Some(String::from("X")), cstore::NativeFramework),
-                       (String::from("c"), None, cstore::NativeUnknown)];
+        v4.libs = vec![(String::from("a"), None, Some(cstore::NativeStatic)),
+                       (String::from("b"), Some(String::from("X")), Some(cstore::NativeFramework)),
+                       (String::from("c"), None, Some(cstore::NativeUnknown))];
 
         assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash());
         assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash());
@@ -2267,17 +2272,17 @@ mod tests {
         let mut v3 = super::basic_options();
 
         // Reference
-        v1.libs = vec![(String::from("a"), None, cstore::NativeStatic),
-                       (String::from("b"), None, cstore::NativeFramework),
-                       (String::from("c"), None, cstore::NativeUnknown)];
+        v1.libs = vec![(String::from("a"), None, Some(cstore::NativeStatic)),
+                       (String::from("b"), None, Some(cstore::NativeFramework)),
+                       (String::from("c"), None, Some(cstore::NativeUnknown))];
 
-        v2.libs = vec![(String::from("b"), None, cstore::NativeFramework),
-                       (String::from("a"), None, cstore::NativeStatic),
-                       (String::from("c"), None, cstore::NativeUnknown)];
+        v2.libs = vec![(String::from("b"), None, Some(cstore::NativeFramework)),
+                       (String::from("a"), None, Some(cstore::NativeStatic)),
+                       (String::from("c"), None, Some(cstore::NativeUnknown))];
 
-        v3.libs = vec![(String::from("c"), None, cstore::NativeUnknown),
-                       (String::from("a"), None, cstore::NativeStatic),
-                       (String::from("b"), None, cstore::NativeFramework)];
+        v3.libs = vec![(String::from("c"), None, Some(cstore::NativeUnknown)),
+                       (String::from("a"), None, Some(cstore::NativeStatic)),
+                       (String::from("b"), None, Some(cstore::NativeFramework))];
 
         assert!(v1.dep_tracking_hash() == v2.dep_tracking_hash());
         assert!(v1.dep_tracking_hash() == v3.dep_tracking_hash());
@@ -2346,6 +2351,10 @@ mod tests {
         assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
 
         opts = reference.clone();
+        opts.cg.overflow_checks = Some(true);
+        assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
+
+        opts = reference.clone();
         opts.cg.no_prepopulate_passes = true;
         assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
 
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index f10ea3544f2..68edcc60779 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -372,6 +372,11 @@ impl Session {
     pub fn nonzeroing_move_hints(&self) -> bool {
         self.opts.debugging_opts.enable_nonzeroing_move_hints
     }
+    pub fn overflow_checks(&self) -> bool {
+        self.opts.cg.overflow_checks
+            .or(self.opts.debugging_opts.force_overflow_checks)
+            .unwrap_or(self.opts.debug_assertions)
+    }
 
     pub fn must_not_eliminate_frame_pointers(&self) -> bool {
         self.opts.debuginfo != DebugInfoLevel::NoDebugInfo ||
diff --git a/src/librustc/ty/adjustment.rs b/src/librustc/ty/adjustment.rs
index 333a5c74cb4..34977822bc6 100644
--- a/src/librustc/ty/adjustment.rs
+++ b/src/librustc/ty/adjustment.rs
@@ -33,6 +33,9 @@ pub enum Adjust<'tcx> {
     /// Go from a safe fn pointer to an unsafe fn pointer.
     UnsafeFnPointer,
 
+    // Go from a non-capturing closure to an fn pointer.
+    ClosureFnPointer,
+
     /// Go from a mut raw pointer to a const raw pointer.
     MutToConstPointer,
 
@@ -120,6 +123,7 @@ impl<'tcx> Adjustment<'tcx> {
 
             Adjust::ReifyFnPointer |
             Adjust::UnsafeFnPointer |
+            Adjust::ClosureFnPointer |
             Adjust::MutToConstPointer |
             Adjust::DerefRef {..} => false,
         }
diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs
index 1d5d1e3ab2f..0c179469448 100644
--- a/src/librustc_back/target/mod.rs
+++ b/src/librustc_back/target/mod.rs
@@ -200,6 +200,7 @@ supported_targets! {
     ("armv7s-apple-ios", armv7s_apple_ios),
 
     ("x86_64-sun-solaris", x86_64_sun_solaris),
+    ("sparcv9-sun-solaris", sparcv9_sun_solaris),
 
     ("x86_64-pc-windows-gnu", x86_64_pc_windows_gnu),
     ("i686-pc-windows-gnu", i686_pc_windows_gnu),
diff --git a/src/librustc_back/target/sparcv9_sun_solaris.rs b/src/librustc_back/target/sparcv9_sun_solaris.rs
new file mode 100644
index 00000000000..c88e5a402f2
--- /dev/null
+++ b/src/librustc_back/target/sparcv9_sun_solaris.rs
@@ -0,0 +1,35 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use target::{Target, TargetResult};
+
+pub fn target() -> TargetResult {
+    let mut base = super::solaris_base::opts();
+    base.pre_link_args.push("-m64".to_string());
+    // llvm calls this "v9"
+    base.cpu = "v9".to_string();
+    base.max_atomic_width = Some(64);
+
+    Ok(Target {
+        llvm_target: "sparcv9-sun-solaris".to_string(),
+        target_endian: "big".to_string(),
+        target_pointer_width: "64".to_string(),
+        data_layout: "E-m:e-i64:64-n32:64-S128".to_string(),
+        // Use "sparc64" instead of "sparcv9" here, since the former is already
+        // used widely in the source base.  If we ever needed ABI
+        // differentiation from the sparc64, we could, but that would probably
+        // just be confusing.
+        arch: "sparc64".to_string(),
+        target_os: "solaris".to_string(),
+        target_env: "".to_string(),
+        target_vendor: "sun".to_string(),
+        options: base,
+    })
+}
diff --git a/src/librustc_const_eval/_match.rs b/src/librustc_const_eval/_match.rs
index 78c4027aa43..5a9f885719c 100644
--- a/src/librustc_const_eval/_match.rs
+++ b/src/librustc_const_eval/_match.rs
@@ -196,6 +196,28 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
             }
         }).clone()
     }
+
+    fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool {
+        if self.tcx.sess.features.borrow().never_type {
+            ty.is_uninhabited_from(self.module, self.tcx)
+        } else {
+            false
+        }
+    }
+
+    fn is_variant_uninhabited(&self,
+                              variant: &'tcx ty::VariantDef,
+                              substs: &'tcx ty::subst::Substs<'tcx>) -> bool
+    {
+        if self.tcx.sess.features.borrow().never_type {
+            let forest = variant.uninhabited_from(
+                &mut FxHashMap::default(), self.tcx, substs, AdtKind::Enum
+            );
+            forest.contains(self.tcx, self.module)
+        } else {
+            false
+        }
+    }
 }
 
 #[derive(Clone, Debug, PartialEq)]
@@ -379,48 +401,32 @@ impl<'tcx> Witness<'tcx> {
 fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
                                   pcx: PatternContext<'tcx>) -> Vec<Constructor>
 {
-    let check_inhabited = cx.tcx.sess.features.borrow().never_type;
     debug!("all_constructors({:?})", pcx.ty);
     match pcx.ty.sty {
         ty::TyBool =>
             [true, false].iter().map(|b| ConstantValue(ConstVal::Bool(*b))).collect(),
         ty::TySlice(ref sub_ty) => {
-            if sub_ty.is_uninhabited_from(cx.module, cx.tcx)
-                && check_inhabited
-            {
+            if cx.is_uninhabited(sub_ty) {
                 vec![Slice(0)]
             } else {
                 (0..pcx.max_slice_length+1).map(|length| Slice(length)).collect()
             }
         }
         ty::TyArray(ref sub_ty, length) => {
-            if length == 0 || !(sub_ty.is_uninhabited_from(cx.module, cx.tcx)
-                                && check_inhabited)
-            {
-                vec![Slice(length)]
-            } else {
+            if length > 0 && cx.is_uninhabited(sub_ty) {
                 vec![]
+            } else {
+                vec![Slice(length)]
             }
         }
         ty::TyAdt(def, substs) if def.is_enum() && def.variants.len() != 1 => {
-            def.variants.iter().filter_map(|v| {
-                let mut visited = FxHashMap::default();
-                let forest = v.uninhabited_from(&mut visited,
-                                                cx.tcx, substs,
-                                                AdtKind::Enum);
-                if forest.contains(cx.tcx, cx.module)
-                    && check_inhabited
-                {
-                    None
-                } else {
-                    Some(Variant(v.did))
-                }
-            }).collect()
+            def.variants.iter()
+                .filter(|v| !cx.is_variant_uninhabited(v, substs))
+                .map(|v| Variant(v.did))
+                .collect()
         }
         _ => {
-            if pcx.ty.is_uninhabited_from(cx.module, cx.tcx)
-                    && check_inhabited
-            {
+            if cx.is_uninhabited(pcx.ty) {
                 vec![]
             } else {
                 vec![Single]
@@ -564,7 +570,6 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
 
     assert!(rows.iter().all(|r| r.len() == v.len()));
 
-
     let pcx = PatternContext {
         ty: rows.iter().map(|r| r[0].ty).find(|ty| !ty.references_error())
             .unwrap_or(v[0].ty),
@@ -590,7 +595,6 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
         let missing_ctors: Vec<Constructor> = all_ctors.iter().filter(|c| {
             !used_ctors.contains(*c)
         }).cloned().collect();
-        debug!("missing_ctors = {:?}", missing_ctors);
 
         // `missing_ctors` is the set of constructors from the same type as the
         // first column of `matrix` that are matched only by wildcard patterns
@@ -599,8 +603,23 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
         // Therefore, if there is some pattern that is unmatched by `matrix`,
         // it will still be unmatched if the first constructor is replaced by
         // any of the constructors in `missing_ctors`
-
-        if missing_ctors.is_empty() {
+        //
+        // However, if our scrutinee is *privately* an empty enum, we
+        // must treat it as though it had an "unknown" constructor (in
+        // that case, all other patterns obviously can't be variants)
+        // to avoid exposing its emptyness. See the `match_privately_empty`
+        // test for details.
+        //
+        // FIXME: currently the only way I know of something can
+        // be a privately-empty enum is when the never_type
+        // feature flag is not present, so this is only
+        // needed for that case.
+
+        let is_privately_empty =
+            all_ctors.is_empty() && !cx.is_uninhabited(pcx.ty);
+        debug!("missing_ctors={:?} is_privately_empty={:?}", missing_ctors,
+               is_privately_empty);
+        if missing_ctors.is_empty() && !is_privately_empty {
             all_ctors.into_iter().map(|c| {
                 is_useful_specialized(cx, matrix, v, c.clone(), pcx.ty, witness)
             }).find(|result| result.is_useful()).unwrap_or(NotUseful)
@@ -649,6 +668,7 @@ fn is_useful_specialized<'p, 'a:'p, 'tcx: 'a>(
     lty: Ty<'tcx>,
     witness: WitnessPreference) -> Usefulness<'tcx>
 {
+    debug!("is_useful_specialized({:?}, {:?}, {:?})", v, ctor, lty);
     let sub_pat_tys = constructor_sub_pattern_tys(cx, &ctor, lty);
     let wild_patterns_owned: Vec<_> = sub_pat_tys.iter().map(|ty| {
         Pattern {
@@ -754,7 +774,19 @@ fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>,
         ty::TyRef(_, ref ty_and_mut) => vec![ty_and_mut.ty],
         ty::TyAdt(adt, substs) => {
             adt.variants[ctor.variant_index_for_adt(adt)].fields.iter().map(|field| {
-                field.ty(cx.tcx, substs)
+                let is_visible = adt.is_enum()
+                    || field.vis.is_accessible_from(cx.module, cx.tcx);
+                if is_visible {
+                    field.ty(cx.tcx, substs)
+                } else {
+                    // Treat all non-visible fields as nil. They
+                    // can't appear in any other pattern from
+                    // this match (because they are private),
+                    // so their type does not matter - but
+                    // we don't want to know they are
+                    // uninhabited.
+                    cx.tcx.mk_nil()
+                }
             }).collect()
         }
         _ => vec![],
diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs
index 6f33b4fad76..9b30946c0be 100644
--- a/src/librustc_const_eval/check_match.rs
+++ b/src/librustc_const_eval/check_match.rs
@@ -177,6 +177,31 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
             // Fourth, check for unreachable arms.
             check_arms(cx, &inlined_arms, source);
 
+            // Then, if the match has no arms, check whether the scrutinee
+            // is uninhabited.
+            let pat_ty = self.tables.node_id_to_type(scrut.id);
+            let module = self.tcx.hir.local_def_id(self.tcx.hir.get_module_parent(scrut.id));
+            if inlined_arms.is_empty() {
+                let scrutinee_is_uninhabited = if self.tcx.sess.features.borrow().never_type {
+                    pat_ty.is_uninhabited_from(module, self.tcx)
+                } else {
+                    self.conservative_is_uninhabited(pat_ty)
+                };
+                if !scrutinee_is_uninhabited {
+                    // We know the type is inhabited, so this must be wrong
+                    let mut err = create_e0004(self.tcx.sess, scrut.span,
+                                               format!("non-exhaustive patterns: type {} \
+                                                        is non-empty",
+                                                       pat_ty));
+                    span_help!(&mut err, scrut.span,
+                               "Please ensure that all possible cases are being handled; \
+                                possibly adding wildcards or more match arms.");
+                    err.emit();
+                }
+                // If the type *is* uninhabited, it's vacuously exhaustive
+                return;
+            }
+
             let matrix: Matrix = inlined_arms
                 .iter()
                 .filter(|&&(_, guard)| guard.is_none())
@@ -188,6 +213,15 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
         })
     }
 
+    fn conservative_is_uninhabited(&self, scrutinee_ty: Ty<'tcx>) -> bool {
+        // "rustc-1.0-style" uncontentious uninhabitableness check
+        match scrutinee_ty.sty {
+            ty::TyNever => true,
+            ty::TyAdt(def, _) => def.variants.is_empty(),
+            _ => false
+        }
+    }
+
     fn check_irrefutable(&self, pat: &Pat, is_fn_arg: bool) {
         let origin = if is_fn_arg {
             "function argument"
diff --git a/src/librustc_incremental/calculate_svh/svh_visitor.rs b/src/librustc_incremental/calculate_svh/svh_visitor.rs
index c7512f2971b..486900fc2fe 100644
--- a/src/librustc_incremental/calculate_svh/svh_visitor.rs
+++ b/src/librustc_incremental/calculate_svh/svh_visitor.rs
@@ -63,8 +63,7 @@ impl<'a, 'hash, 'tcx> StrictVersionHashVisitor<'a, 'hash, 'tcx> {
                hash_spans: bool,
                hash_bodies: bool)
                -> Self {
-        let check_overflow = tcx.sess.opts.debugging_opts.force_overflow_checks
-            .unwrap_or(tcx.sess.opts.debug_assertions);
+        let check_overflow = tcx.sess.overflow_checks();
 
         StrictVersionHashVisitor {
             st: st,
@@ -338,8 +337,10 @@ fn saw_expr<'a>(node: &'a Expr_,
         ExprIndex(..)            => (SawExprIndex, true),
         ExprPath(_)              => (SawExprPath, false),
         ExprAddrOf(m, _)         => (SawExprAddrOf(m), false),
-        ExprBreak(label, _)      => (SawExprBreak(label.map(|l| l.name.as_str())), false),
-        ExprAgain(label)         => (SawExprAgain(label.map(|l| l.name.as_str())), false),
+        ExprBreak(label, _)      => (SawExprBreak(label.ident.map(|i|
+                                                    i.node.name.as_str())), false),
+        ExprAgain(label)         => (SawExprAgain(label.ident.map(|i|
+                                                    i.node.name.as_str())), false),
         ExprRet(..)              => (SawExprRet, false),
         ExprInlineAsm(ref a,..)  => (SawExprInlineAsm(StableInlineAsm(a)), false),
         ExprStruct(..)           => (SawExprStruct, false),
diff --git a/src/librustc_incremental/persist/data.rs b/src/librustc_incremental/persist/data.rs
index 60f24b71de2..673f1ae1084 100644
--- a/src/librustc_incremental/persist/data.rs
+++ b/src/librustc_incremental/persist/data.rs
@@ -23,6 +23,11 @@ use super::directory::DefPathIndex;
 pub struct SerializedDepGraph {
     pub edges: Vec<SerializedEdgeSet>,
 
+    /// These are output nodes that have no incoming edges. We track
+    /// these separately so that when we reload all edges, we don't
+    /// lose track of these nodes.
+    pub bootstrap_outputs: Vec<DepNode<DefPathIndex>>,
+
     /// These are hashes of two things:
     /// - the HIR nodes in this crate
     /// - the metadata nodes from dependent crates we use
diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs
index 7724658a9d6..03411e01a57 100644
--- a/src/librustc_incremental/persist/load.rs
+++ b/src/librustc_incremental/persist/load.rs
@@ -184,6 +184,18 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         }
     }
 
+    // Recreate bootstrap outputs, which are outputs that have no incoming edges (and hence cannot
+    // be dirty).
+    for bootstrap_output in &serialized_dep_graph.bootstrap_outputs {
+        if let Some(n) = retraced.map(bootstrap_output) {
+            if let DepNode::WorkProduct(ref wp) = n {
+                clean_work_products.insert(wp.clone());
+            }
+
+            tcx.dep_graph.with_task(n, || ()); // create the node with no inputs
+        }
+    }
+
     // Subtle. Sometimes we have intermediate nodes that we can't recreate in the new graph.
     // This is pretty unusual but it arises in a scenario like this:
     //
diff --git a/src/librustc_incremental/persist/preds/mod.rs b/src/librustc_incremental/persist/preds/mod.rs
index a80620fbde6..f6a37c7a122 100644
--- a/src/librustc_incremental/persist/preds/mod.rs
+++ b/src/librustc_incremental/persist/preds/mod.rs
@@ -11,7 +11,7 @@
 use rustc::dep_graph::{DepGraphQuery, DepNode};
 use rustc::hir::def_id::DefId;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::graph::Graph;
+use rustc_data_structures::graph::{Graph, NodeIndex};
 
 use super::hash::*;
 use ich::Fingerprint;
@@ -28,6 +28,14 @@ pub struct Predecessors<'query> {
     // of the graph down.
     pub reduced_graph: Graph<&'query DepNode<DefId>, ()>,
 
+    // These are output nodes that have no incoming edges. We have to
+    // track these specially because, when we load the data back up
+    // again, we want to make sure and recreate these nodes (we want
+    // to recreate the nodes where all incoming edges are clean; but
+    // since we ordinarily just serialize edges, we wind up just
+    // forgetting that bootstrap outputs even exist in that case.)
+    pub bootstrap_outputs: Vec<&'query DepNode<DefId>>,
+
     // For the inputs (hir/foreign-metadata), we include hashes.
     pub hashes: FxHashMap<&'query DepNode<DefId>, Fingerprint>,
 }
@@ -57,7 +65,7 @@ impl<'q> Predecessors<'q> {
 
         // Reduce the graph to the most important nodes.
         let compress::Reduction { graph, input_nodes } =
-            compress::reduce_graph(&query.graph, HashContext::is_hashable, is_output);
+            compress::reduce_graph(&query.graph, HashContext::is_hashable, |n| is_output(n));
 
         let mut hashes = FxHashMap();
         for input_index in input_nodes {
@@ -67,8 +75,17 @@ impl<'q> Predecessors<'q> {
                   .or_insert_with(|| hcx.hash(input).unwrap());
         }
 
+        let bootstrap_outputs: Vec<&'q DepNode<DefId>> =
+            (0 .. graph.len_nodes())
+            .map(NodeIndex)
+            .filter(|&n| graph.incoming_edges(n).next().is_none())
+            .map(|n| *graph.node_data(n))
+            .filter(|n| is_output(n))
+            .collect();
+
         Predecessors {
             reduced_graph: graph,
+            bootstrap_outputs: bootstrap_outputs,
             hashes: hashes,
         }
     }
diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs
index 34bb125ef3f..dfa6bf6bbb5 100644
--- a/src/librustc_incremental/persist/save.rs
+++ b/src/librustc_incremental/persist/save.rs
@@ -204,11 +204,15 @@ pub fn encode_dep_graph(preds: &Predecessors,
     }
 
     // Create the serialized dep-graph.
+    let bootstrap_outputs = preds.bootstrap_outputs.iter()
+                                                   .map(|n| builder.map(n))
+                                                   .collect();
     let edges = edges.into_iter()
                      .map(|(k, v)| SerializedEdgeSet { source: k, targets: v })
                      .collect();
     let graph = SerializedDepGraph {
-        edges: edges,
+        bootstrap_outputs,
+        edges,
         hashes: preds.hashes
             .iter()
             .map(|(&dep_node, &hash)| {
@@ -221,6 +225,7 @@ pub fn encode_dep_graph(preds: &Predecessors,
     };
 
     if tcx.sess.opts.debugging_opts.incremental_info {
+        println!("incremental: {} nodes in reduced dep-graph", preds.reduced_graph.len_nodes());
         println!("incremental: {} edges in serialized dep-graph", graph.edges.len());
         println!("incremental: {} hashes in serialized dep-graph", graph.hashes.len());
     }
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index 104d76b1f60..4477488f6cb 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -1077,10 +1077,20 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> {
             let mut found = false;
             for lib in self.cstore.get_used_libraries().borrow_mut().iter_mut() {
                 if lib.name == name as &str {
-                    lib.kind = kind;
+                    let mut changed = false;
+                    if let Some(k) = kind {
+                        lib.kind = k;
+                        changed = true;
+                    }
                     if let &Some(ref new_name) = new_name {
                         lib.name = Symbol::intern(new_name);
+                        changed = true;
+                    }
+                    if !changed {
+                        self.sess.warn(&format!("redundant linker flag specified for library `{}`",
+                                                name));
                     }
+
                     found = true;
                 }
             }
@@ -1089,7 +1099,7 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> {
                 let new_name = new_name.as_ref().map(|s| &**s); // &Option<String> -> Option<&str>
                 let lib = NativeLibrary {
                     name: Symbol::intern(new_name.unwrap_or(name)),
-                    kind: kind,
+                    kind: if let Some(k) = kind { k } else { cstore::NativeUnknown },
                     cfg: None,
                     foreign_items: Vec::new(),
                 };
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index abc3ffcf86b..53883e50a5b 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -39,6 +39,7 @@ use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque};
 use syntax::attr;
 use syntax::ast;
 use syntax::codemap;
+use syntax::ext::base::MacroKind;
 use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP};
 
 pub struct DecodeContext<'a, 'tcx: 'a> {
@@ -434,7 +435,7 @@ impl<'tcx> EntryKind<'tcx> {
             EntryKind::Variant(_) => Def::Variant(did),
             EntryKind::Trait(_) => Def::Trait(did),
             EntryKind::Enum(..) => Def::Enum(did),
-            EntryKind::MacroDef(_) => Def::Macro(did),
+            EntryKind::MacroDef(_) => Def::Macro(did, MacroKind::Bang),
 
             EntryKind::ForeignMod |
             EntryKind::Impl(_) |
@@ -483,9 +484,11 @@ impl<'a, 'tcx> CrateMetadata {
     }
 
     pub fn get_def(&self, index: DefIndex) -> Option<Def> {
-        match self.is_proc_macro(index) {
-            true => Some(Def::Macro(self.local_def_id(index))),
-            false => self.entry(index).kind.to_def(self.local_def_id(index)),
+        if !self.is_proc_macro(index) {
+            self.entry(index).kind.to_def(self.local_def_id(index))
+        } else {
+            let kind = self.proc_macros.as_ref().unwrap()[index.as_usize() - 1].1.kind();
+            Some(Def::Macro(self.local_def_id(index), kind))
         }
     }
 
@@ -688,8 +691,14 @@ impl<'a, 'tcx> CrateMetadata {
     {
         if let Some(ref proc_macros) = self.proc_macros {
             if id == CRATE_DEF_INDEX {
-                for (id, &(name, _)) in proc_macros.iter().enumerate() {
-                    let def = Def::Macro(DefId { krate: self.cnum, index: DefIndex::new(id + 1) });
+                for (id, &(name, ref ext)) in proc_macros.iter().enumerate() {
+                    let def = Def::Macro(
+                        DefId {
+                            krate: self.cnum,
+                            index: DefIndex::new(id + 1)
+                        },
+                        ext.kind()
+                    );
                     callback(def::Export { name: name, def: def });
                 }
             }
diff --git a/src/librustc_mir/build/expr/as_lvalue.rs b/src/librustc_mir/build/expr/as_lvalue.rs
index 0487e277a33..5abfe084f22 100644
--- a/src/librustc_mir/build/expr/as_lvalue.rs
+++ b/src/librustc_mir/build/expr/as_lvalue.rs
@@ -99,6 +99,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             ExprKind::Use { .. } |
             ExprKind::NeverToAny { .. } |
             ExprKind::ReifyFnPointer { .. } |
+            ExprKind::ClosureFnPointer { .. } |
             ExprKind::UnsafeFnPointer { .. } |
             ExprKind::Unsize { .. } |
             ExprKind::Repeat { .. } |
diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs
index 7adcc0e730b..7f5d9c36ece 100644
--- a/src/librustc_mir/build/expr/as_rvalue.rs
+++ b/src/librustc_mir/build/expr/as_rvalue.rs
@@ -112,6 +112,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 let source = unpack!(block = this.as_operand(block, source));
                 block.and(Rvalue::Cast(CastKind::UnsafeFnPointer, source, expr.ty))
             }
+            ExprKind::ClosureFnPointer { source } => {
+                let source = unpack!(block = this.as_operand(block, source));
+                block.and(Rvalue::Cast(CastKind::ClosureFnPointer, source, expr.ty))
+            }
             ExprKind::Unsize { source } => {
                 let source = unpack!(block = this.as_operand(block, source));
                 block.and(Rvalue::Cast(CastKind::Unsize, source, expr.ty))
diff --git a/src/librustc_mir/build/expr/category.rs b/src/librustc_mir/build/expr/category.rs
index 6e57c10964c..35173bb598c 100644
--- a/src/librustc_mir/build/expr/category.rs
+++ b/src/librustc_mir/build/expr/category.rs
@@ -70,6 +70,7 @@ impl Category {
             ExprKind::Cast { .. } |
             ExprKind::Use { .. } |
             ExprKind::ReifyFnPointer { .. } |
+            ExprKind::ClosureFnPointer { .. } |
             ExprKind::UnsafeFnPointer { .. } |
             ExprKind::Unsize { .. } |
             ExprKind::Repeat { .. } |
diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs
index e66f2b4e2bf..d9f71e36e21 100644
--- a/src/librustc_mir/build/expr/into.rs
+++ b/src/librustc_mir/build/expr/into.rs
@@ -244,6 +244,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             ExprKind::Cast { .. } |
             ExprKind::Use { .. } |
             ExprKind::ReifyFnPointer { .. } |
+            ExprKind::ClosureFnPointer { .. } |
             ExprKind::UnsafeFnPointer { .. } |
             ExprKind::Unsize { .. } |
             ExprKind::Repeat { .. } |
diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs
index c702a142fab..282361fc13e 100644
--- a/src/librustc_mir/build/scope.rs
+++ b/src/librustc_mir/build/scope.rs
@@ -385,22 +385,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
     /// resolving `break` and `continue`.
     pub fn find_loop_scope(&mut self,
                            span: Span,
-                           label: Option<CodeExtent>)
+                           label: CodeExtent)
                            -> &mut LoopScope<'tcx> {
-        let loop_scopes = &mut self.loop_scopes;
-        match label {
-            None => {
-                // no label? return the innermost loop scope
-                loop_scopes.iter_mut().rev().next()
-            }
-            Some(label) => {
-                // otherwise, find the loop-scope with the correct id
-                loop_scopes.iter_mut()
-                           .rev()
-                           .filter(|loop_scope| loop_scope.extent == label)
-                           .next()
-            }
-        }.unwrap_or_else(|| span_bug!(span, "no enclosing loop scope found?"))
+        // find the loop-scope with the correct id
+        self.loop_scopes.iter_mut()
+            .rev()
+            .filter(|loop_scope| loop_scope.extent == label)
+            .next()
+            .unwrap_or_else(|| span_bug!(span, "no enclosing loop scope found?"))
     }
 
     /// Given a span and the current visibility scope, make a SourceInfo.
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index 7eaf1fe1398..dd45b1b4896 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -60,6 +60,15 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
                     kind: ExprKind::UnsafeFnPointer { source: expr.to_ref() },
                 };
             }
+            Some((ty::adjustment::Adjust::ClosureFnPointer, adjusted_ty)) => {
+                expr = Expr {
+                    temp_lifetime: temp_lifetime,
+                    temp_lifetime_was_shrunk: was_shrunk,
+                    ty: adjusted_ty,
+                    span: self.span,
+                    kind: ExprKind::ClosureFnPointer { source: expr.to_ref() },
+                };
+            }
             Some((ty::adjustment::Adjust::NeverToAny, adjusted_ty)) => {
                 expr = Expr {
                     temp_lifetime: temp_lifetime,
@@ -605,14 +614,21 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
         }
         hir::ExprRet(ref v) => ExprKind::Return { value: v.to_ref() },
         hir::ExprBreak(label, ref value) => {
-            ExprKind::Break {
-                label: label.map(|label| cx.tcx.region_maps.node_extent(label.loop_id)),
-                value: value.to_ref(),
+            match label.loop_id.into() {
+                Ok(loop_id) => ExprKind::Break {
+                    label: cx.tcx.region_maps.node_extent(loop_id),
+                    value: value.to_ref(),
+                },
+                Err(err) => bug!("invalid loop id for break: {}", err)
             }
+
         }
         hir::ExprAgain(label) => {
-            ExprKind::Continue {
-                label: label.map(|label| cx.tcx.region_maps.node_extent(label.loop_id)),
+            match label.loop_id.into() {
+                Ok(loop_id) => ExprKind::Continue {
+                    label: cx.tcx.region_maps.node_extent(loop_id),
+                },
+                Err(err) => bug!("invalid loop id for continue: {}", err)
             }
         }
         hir::ExprMatch(ref discr, ref arms, _) => {
diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs
index 5b3297cb694..852c34a544a 100644
--- a/src/librustc_mir/hair/cx/mod.rs
+++ b/src/librustc_mir/hair/cx/mod.rs
@@ -59,13 +59,8 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
         let mut check_overflow = attrs.iter()
             .any(|item| item.check_name("rustc_inherit_overflow_checks"));
 
-        // Respect -Z force-overflow-checks=on and -C debug-assertions.
-        check_overflow |= infcx.tcx
-            .sess
-            .opts
-            .debugging_opts
-            .force_overflow_checks
-            .unwrap_or(infcx.tcx.sess.opts.debug_assertions);
+        // Respect -C overflow-checks.
+        check_overflow |= infcx.tcx.sess.overflow_checks();
 
         // Constants and const fn's always need overflow checks.
         check_overflow |= constness == hir::Constness::Const;
diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs
index 4ac67cfb2fc..9c7ee6a9ce8 100644
--- a/src/librustc_mir/hair/mod.rs
+++ b/src/librustc_mir/hair/mod.rs
@@ -152,6 +152,9 @@ pub enum ExprKind<'tcx> {
     ReifyFnPointer {
         source: ExprRef<'tcx>,
     },
+    ClosureFnPointer {
+        source: ExprRef<'tcx>,
+    },
     UnsafeFnPointer {
         source: ExprRef<'tcx>,
     },
@@ -205,11 +208,11 @@ pub enum ExprKind<'tcx> {
         arg: ExprRef<'tcx>,
     },
     Break {
-        label: Option<CodeExtent>,
+        label: CodeExtent,
         value: Option<ExprRef<'tcx>>,
     },
     Continue {
-        label: Option<CodeExtent>,
+        label: CodeExtent,
     },
     Return {
         value: Option<ExprRef<'tcx>>,
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 4459142cfb2..04e809ef9d8 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -619,6 +619,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
             Rvalue::CheckedBinaryOp(..) |
             Rvalue::Cast(CastKind::ReifyFnPointer, ..) |
             Rvalue::Cast(CastKind::UnsafeFnPointer, ..) |
+            Rvalue::Cast(CastKind::ClosureFnPointer, ..) |
             Rvalue::Cast(CastKind::Unsize, ..) => {}
 
             Rvalue::Len(_) => {
diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs
index 0b55513f831..e3772a09968 100644
--- a/src/librustc_passes/consts.rs
+++ b/src/librustc_passes/consts.rs
@@ -447,6 +447,7 @@ fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Exp
         Some(Adjust::NeverToAny) |
         Some(Adjust::ReifyFnPointer) |
         Some(Adjust::UnsafeFnPointer) |
+        Some(Adjust::ClosureFnPointer) |
         Some(Adjust::MutToConstPointer) => {}
 
         Some(Adjust::DerefRef { autoderefs, .. }) => {
diff --git a/src/librustc_passes/diagnostics.rs b/src/librustc_passes/diagnostics.rs
index ef871959176..5f06eadb84a 100644
--- a/src/librustc_passes/diagnostics.rs
+++ b/src/librustc_passes/diagnostics.rs
@@ -241,6 +241,22 @@ match 5u32 {
 }
 ```
 "##,
+
+E0590: r##"
+`break` or `continue` must include a label when used in the condition of a
+`while` loop.
+
+Example of erroneous code:
+
+```compile_fail
+while break {}
+```
+
+To fix this, add a label specifying which loop is being broken out of:
+```
+`foo: while break `foo {}
+```
+"##
 }
 
 register_diagnostics! {
diff --git a/src/librustc_passes/loops.rs b/src/librustc_passes/loops.rs
index a5bd69fff01..b2d51be5bf7 100644
--- a/src/librustc_passes/loops.rs
+++ b/src/librustc_passes/loops.rs
@@ -87,23 +87,26 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
                 self.with_context(Closure, |v| v.visit_nested_body(b));
             }
             hir::ExprBreak(label, ref opt_expr) => {
+                let loop_id = match label.loop_id.into() {
+                    Ok(loop_id) => loop_id,
+                    Err(hir::LoopIdError::OutsideLoopScope) => ast::DUMMY_NODE_ID,
+                    Err(hir::LoopIdError::UnlabeledCfInWhileCondition) => {
+                        self.emit_unlabled_cf_in_while_condition(e.span, "break");
+                        ast::DUMMY_NODE_ID
+                    },
+                    Err(hir::LoopIdError::UnresolvedLabel) => ast::DUMMY_NODE_ID,
+                };
+
                 if opt_expr.is_some() {
-                    let loop_kind = if let Some(label) = label {
-                        if label.loop_id == ast::DUMMY_NODE_ID {
-                            None
-                        } else {
-                            Some(match self.hir_map.expect_expr(label.loop_id).node {
-                                hir::ExprWhile(..) => LoopKind::WhileLoop,
-                                hir::ExprLoop(_, _, source) => LoopKind::Loop(source),
-                                ref r => span_bug!(e.span,
-                                                   "break label resolved to a non-loop: {:?}", r),
-                            })
-                        }
-                    } else if let Loop(kind) = self.cx {
-                        Some(kind)
-                    } else {
-                        // `break` outside a loop - caught below
+                    let loop_kind = if loop_id == ast::DUMMY_NODE_ID {
                         None
+                    } else {
+                        Some(match self.hir_map.expect_expr(loop_id).node {
+                            hir::ExprWhile(..) => LoopKind::WhileLoop,
+                            hir::ExprLoop(_, _, source) => LoopKind::Loop(source),
+                            ref r => span_bug!(e.span,
+                                               "break label resolved to a non-loop: {:?}", r),
+                        })
                     };
                     match loop_kind {
                         None | Some(LoopKind::Loop(hir::LoopSource::Loop)) => (),
@@ -117,9 +120,15 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
                         }
                     }
                 }
+
                 self.require_loop("break", e.span);
             }
-            hir::ExprAgain(_) => self.require_loop("continue", e.span),
+            hir::ExprAgain(label) => {
+                if let Err(hir::LoopIdError::UnlabeledCfInWhileCondition) = label.loop_id.into() {
+                    self.emit_unlabled_cf_in_while_condition(e.span, "continue");
+                }
+                self.require_loop("continue", e.span)
+            },
             _ => intravisit::walk_expr(self, e),
         }
     }
@@ -150,4 +159,12 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> {
             }
         }
     }
+
+    fn emit_unlabled_cf_in_while_condition(&mut self, span: Span, cf_type: &str) {
+        struct_span_err!(self.sess, span, E0590,
+                         "`break` or `continue` with no label in the condition of a `while` loop")
+            .span_label(span,
+                        &format!("unlabeled `{}` in the condition of a `while` loop", cf_type))
+            .emit();
+    }
 }
diff --git a/src/librustc_passes/static_recursion.rs b/src/librustc_passes/static_recursion.rs
index 1ef8a5b0080..fc05471ead3 100644
--- a/src/librustc_passes/static_recursion.rs
+++ b/src/librustc_passes/static_recursion.rs
@@ -18,7 +18,6 @@ use rustc::hir::def::{Def, CtorKind};
 use rustc::util::nodemap::{NodeMap, NodeSet};
 
 use syntax::ast;
-use syntax::feature_gate::{GateIssue, emit_feature_err};
 use syntax_pos::Span;
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use rustc::hir;
@@ -43,7 +42,7 @@ impl<'a, 'hir: 'a> Visitor<'hir> for CheckCrateVisitor<'a, 'hir> {
         match it.node {
             hir::ItemStatic(..) |
             hir::ItemConst(..) => {
-                let mut recursion_visitor = CheckItemRecursionVisitor::new(self, &it.span);
+                let mut recursion_visitor = CheckItemRecursionVisitor::new(self);
                 recursion_visitor.visit_item(it);
             }
             hir::ItemEnum(ref enum_def, ref generics) => {
@@ -52,8 +51,7 @@ impl<'a, 'hir: 'a> Visitor<'hir> for CheckCrateVisitor<'a, 'hir> {
                 // less redundant output.
                 for variant in &enum_def.variants {
                     if let Some(_) = variant.node.disr_expr {
-                        let mut recursion_visitor = CheckItemRecursionVisitor::new(self,
-                                                                                   &variant.span);
+                        let mut recursion_visitor = CheckItemRecursionVisitor::new(self);
                         recursion_visitor.populate_enum_discriminants(enum_def);
                         recursion_visitor.visit_variant(variant, generics, it.id);
                     }
@@ -68,7 +66,7 @@ impl<'a, 'hir: 'a> Visitor<'hir> for CheckCrateVisitor<'a, 'hir> {
         match ti.node {
             hir::TraitItemKind::Const(_, ref default) => {
                 if let Some(_) = *default {
-                    let mut recursion_visitor = CheckItemRecursionVisitor::new(self, &ti.span);
+                    let mut recursion_visitor = CheckItemRecursionVisitor::new(self);
                     recursion_visitor.visit_trait_item(ti);
                 }
             }
@@ -80,7 +78,7 @@ impl<'a, 'hir: 'a> Visitor<'hir> for CheckCrateVisitor<'a, 'hir> {
     fn visit_impl_item(&mut self, ii: &'hir hir::ImplItem) {
         match ii.node {
             hir::ImplItemKind::Const(..) => {
-                let mut recursion_visitor = CheckItemRecursionVisitor::new(self, &ii.span);
+                let mut recursion_visitor = CheckItemRecursionVisitor::new(self);
                 recursion_visitor.visit_impl_item(ii);
             }
             _ => {}
@@ -105,7 +103,6 @@ pub fn check_crate<'hir>(sess: &Session, hir_map: &hir_map::Map<'hir>) -> Compil
 }
 
 struct CheckItemRecursionVisitor<'a, 'b: 'a, 'hir: 'b> {
-    root_span: &'b Span,
     sess: &'b Session,
     hir_map: &'b hir_map::Map<'hir>,
     discriminant_map: &'a mut NodeMap<Option<hir::BodyId>>,
@@ -114,9 +111,8 @@ struct CheckItemRecursionVisitor<'a, 'b: 'a, 'hir: 'b> {
 }
 
 impl<'a, 'b: 'a, 'hir: 'b> CheckItemRecursionVisitor<'a, 'b, 'hir> {
-    fn new(v: &'a mut CheckCrateVisitor<'b, 'hir>, span: &'b Span) -> Self {
+    fn new(v: &'a mut CheckCrateVisitor<'b, 'hir>) -> Self {
         CheckItemRecursionVisitor {
-            root_span: span,
             sess: v.sess,
             hir_map: v.hir_map,
             discriminant_map: &mut v.discriminant_map,
@@ -143,15 +139,7 @@ impl<'a, 'b: 'a, 'hir: 'b> CheckItemRecursionVisitor<'a, 'b, 'hir> {
                     false
                 }
             });
-            if any_static {
-                if !self.sess.features.borrow().static_recursion {
-                    emit_feature_err(&self.sess.parse_sess,
-                                     "static_recursion",
-                                     *self.root_span,
-                                     GateIssue::Language,
-                                     "recursive static");
-                }
-            } else {
+            if !any_static {
                 struct_span_err!(self.sess, span, E0265, "recursive constant")
                     .span_label(span, &format!("recursion not allowed in constant"))
                     .emit();
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 4679b6be88b..ec02e9235be 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -495,7 +495,7 @@ impl<'a> Resolver<'a> {
 
     pub fn get_macro(&mut self, def: Def) -> Rc<SyntaxExtension> {
         let def_id = match def {
-            Def::Macro(def_id) => def_id,
+            Def::Macro(def_id, ..) => def_id,
             _ => panic!("Expected Def::Macro(..)"),
         };
         if let Some(ext) = self.macro_map.get(&def_id) {
@@ -537,7 +537,6 @@ impl<'a> Resolver<'a> {
                            binding: &'a NameBinding<'a>,
                            span: Span,
                            allow_shadowing: bool) {
-        self.macro_names.insert(name);
         if self.builtin_macros.insert(name, binding).is_some() && !allow_shadowing {
             let msg = format!("`{}` is already in scope", name);
             let note =
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index c9e870188aa..eefe83d7da6 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -1265,7 +1265,7 @@ impl<'a> Resolver<'a> {
             ribs: PerNS {
                 value_ns: vec![Rib::new(ModuleRibKind(graph_root))],
                 type_ns: vec![Rib::new(ModuleRibKind(graph_root))],
-                macro_ns: None,
+                macro_ns: Some(vec![Rib::new(ModuleRibKind(graph_root))]),
             },
             label_ribs: Vec::new(),
 
@@ -2328,10 +2328,13 @@ impl<'a> Resolver<'a> {
                 };
             }
         }
-        if primary_ns != MacroNS && path.len() == 1 &&
-                self.macro_names.contains(&path[0].name) {
+        let is_builtin = self.builtin_macros.get(&path[0].name).cloned()
+            .map(|binding| binding.get_macro(self).kind() == MacroKind::Bang).unwrap_or(false);
+        if primary_ns != MacroNS && (is_builtin || self.macro_names.contains(&path[0].name)) {
             // Return some dummy definition, it's enough for error reporting.
-            return Some(PathResolution::new(Def::Macro(DefId::local(CRATE_DEF_INDEX))));
+            return Some(
+                PathResolution::new(Def::Macro(DefId::local(CRATE_DEF_INDEX), MacroKind::Bang))
+            );
         }
         fin_res
     }
@@ -2768,18 +2771,24 @@ impl<'a> Resolver<'a> {
         }
     }
 
-    fn resolve_labeled_block(&mut self, label: Option<SpannedIdent>, id: NodeId, block: &Block) {
+    fn with_resolved_label<F>(&mut self, label: Option<SpannedIdent>, id: NodeId, f: F)
+        where F: FnOnce(&mut Resolver)
+    {
         if let Some(label) = label {
             let def = Def::Label(id);
             self.with_label_rib(|this| {
                 this.label_ribs.last_mut().unwrap().bindings.insert(label.node, def);
-                this.visit_block(block);
+                f(this);
             });
         } else {
-            self.visit_block(block);
+            f(self);
         }
     }
 
+    fn resolve_labeled_block(&mut self, label: Option<SpannedIdent>, id: NodeId, block: &Block) {
+        self.with_resolved_label(label, id, |this| this.visit_block(block));
+    }
+
     fn resolve_expr(&mut self, expr: &Expr, parent: Option<&ExprKind>) {
         // First, record candidate traits for this expression if it could
         // result in the invocation of a method call.
@@ -2833,18 +2842,18 @@ impl<'a> Resolver<'a> {
             ExprKind::Loop(ref block, label) => self.resolve_labeled_block(label, expr.id, &block),
 
             ExprKind::While(ref subexpression, ref block, label) => {
-                self.visit_expr(subexpression);
-                self.resolve_labeled_block(label, expr.id, &block);
+                self.with_resolved_label(label, expr.id, |this| {
+                    this.visit_expr(subexpression);
+                    this.visit_block(block);
+                });
             }
 
             ExprKind::WhileLet(ref pattern, ref subexpression, ref block, label) => {
-                self.visit_expr(subexpression);
-                self.ribs[ValueNS].push(Rib::new(NormalRibKind));
-                self.resolve_pattern(pattern, PatternSource::WhileLet, &mut FxHashMap());
-
-                self.resolve_labeled_block(label, expr.id, block);
-
-                self.ribs[ValueNS].pop();
+                self.with_resolved_label(label, expr.id, |this| {
+                    this.visit_expr(subexpression);
+                    this.resolve_pattern(pattern, PatternSource::WhileLet, &mut FxHashMap());
+                    this.visit_block(block);
+                });
             }
 
             ExprKind::ForLoop(ref pattern, ref subexpression, ref block, label) => {
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index aba2de6b3a2..b7068f4b09f 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -23,7 +23,7 @@ use syntax::ast::{self, Name, Ident};
 use syntax::attr;
 use syntax::errors::DiagnosticBuilder;
 use syntax::ext::base::{self, Determinacy, MultiModifier, MultiDecorator};
-use syntax::ext::base::{NormalTT, Resolver as SyntaxResolver, SyntaxExtension};
+use syntax::ext::base::{Resolver as SyntaxResolver, SyntaxExtension};
 use syntax::ext::base::MacroKind;
 use syntax::ext::expand::{Expansion, mark_tts};
 use syntax::ext::hygiene::Mark;
@@ -152,16 +152,14 @@ impl<'a> base::Resolver for Resolver<'a> {
     }
 
     fn add_ext(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>) {
-        if let NormalTT(..) = *ext {
-            self.macro_names.insert(ident.name);
-        }
         let def_id = DefId {
             krate: BUILTIN_MACROS_CRATE,
             index: DefIndex::new(self.macro_map.len()),
         };
+        let kind = ext.kind();
         self.macro_map.insert(def_id, ext);
         let binding = self.arenas.alloc_name_binding(NameBinding {
-            kind: NameBindingKind::Def(Def::Macro(def_id)),
+            kind: NameBindingKind::Def(Def::Macro(def_id, kind)),
             span: DUMMY_SP,
             vis: ty::Visibility::Invisible,
             expansion: Mark::root(),
@@ -470,24 +468,40 @@ impl<'a> Resolver<'a> {
 
     fn suggest_macro_name(&mut self, name: &str, kind: MacroKind,
                           err: &mut DiagnosticBuilder<'a>) {
-        let suggestion = match kind {
-            MacroKind::Bang =>
-                find_best_match_for_name(self.macro_names.iter(), name, None),
-            MacroKind::Attr |
-            MacroKind::Derive => {
-                // Find a suggestion from the legacy namespace.
-                // FIXME: get_macro needs an &mut Resolver, can we do it without cloning?
-                let builtin_macros = self.builtin_macros.clone();
-                let names = builtin_macros.iter().filter_map(|(name, binding)| {
-                    if binding.get_macro(self).kind() == kind {
-                        Some(name)
-                    } else {
-                        None
-                    }
-                });
-                find_best_match_for_name(names, name, None)
+        // First check if this is a locally-defined bang macro.
+        let suggestion = if let MacroKind::Bang = kind {
+            find_best_match_for_name(self.macro_names.iter(), name, None)
+        } else {
+            None
+        // Then check builtin macros.
+        }.or_else(|| {
+            // FIXME: get_macro needs an &mut Resolver, can we do it without cloning?
+            let builtin_macros = self.builtin_macros.clone();
+            let names = builtin_macros.iter().filter_map(|(name, binding)| {
+                if binding.get_macro(self).kind() == kind {
+                    Some(name)
+                } else {
+                    None
+                }
+            });
+            find_best_match_for_name(names, name, None)
+        // Then check modules.
+        }).or_else(|| {
+            if !self.use_extern_macros {
+                return None;
             }
-        };
+            let is_macro = |def| {
+                if let Def::Macro(_, def_kind) = def {
+                    def_kind == kind
+                } else {
+                    false
+                }
+            };
+            let ident = Ident::from_str(name);
+            self.lookup_typo_candidate(&vec![ident], MacroNS, is_macro)
+                .as_ref().map(|s| Symbol::intern(s))
+        });
+
         if let Some(suggestion) = suggestion {
             if suggestion != name {
                 if let MacroKind::Bang = kind {
@@ -566,7 +580,7 @@ impl<'a> Resolver<'a> {
             });
             self.macro_exports.push(Export {
                 name: def.ident.name,
-                def: Def::Macro(self.definitions.local_def_id(def.id)),
+                def: Def::Macro(self.definitions.local_def_id(def.id), MacroKind::Bang),
             });
             self.exported_macros.push(def);
         }
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index 292f1eb1366..6667a3199a8 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -336,7 +336,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
             Def::AssociatedTy(..) |
             Def::AssociatedConst(..) |
             Def::PrimTy(_) |
-            Def::Macro(_) |
+            Def::Macro(..) |
             Def::Err => {
                span_bug!(span,
                          "process_def_kind for unexpected item: {:?}",
diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs
index a476b1d29e5..f742cca5b98 100644
--- a/src/librustc_trans/abi.rs
+++ b/src/librustc_trans/abi.rs
@@ -506,7 +506,11 @@ impl FnType {
                 if let Some(inner) = rust_ptr_attrs(ty, &mut data) {
                     data.attrs.set(ArgAttribute::NonNull);
                     if ccx.tcx().struct_tail(inner).is_trait() {
+                        // vtables can be safely marked non-null, readonly
+                        // and noalias.
                         info.attrs.set(ArgAttribute::NonNull);
+                        info.attrs.set(ArgAttribute::ReadOnly);
+                        info.attrs.set(ArgAttribute::NoAlias);
                     }
                 }
                 args.push(data);
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index 41c0eaa52a7..ca746c58e7f 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -472,8 +472,15 @@ pub fn load_fat_ptr<'a, 'tcx>(
         b.load(ptr, alignment.to_align())
     };
 
-    // FIXME: emit metadata on `meta`.
-    let meta = b.load(get_meta(b, src), alignment.to_align());
+    let meta = get_meta(b, src);
+    let meta_ty = val_ty(meta);
+    // If the 'meta' field is a pointer, it's a vtable, so use load_nonnull
+    // instead
+    let meta = if meta_ty.element_type().kind() == llvm::TypeKind::Pointer {
+        b.load_nonnull(meta, None)
+    } else {
+        b.load(meta, None)
+    };
 
     (ptr, meta)
 }
@@ -1132,11 +1139,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let ty::CrateAnalysis { export_map, reachable, name, .. } = analysis;
     let exported_symbols = find_exported_symbols(tcx, reachable);
 
-    let check_overflow = if let Some(v) = tcx.sess.opts.debugging_opts.force_overflow_checks {
-        v
-    } else {
-        tcx.sess.opts.debug_assertions
-    };
+    let check_overflow = tcx.sess.overflow_checks();
 
     let link_meta = link::build_link_meta(incremental_hashes_map, &name);
 
diff --git a/src/librustc_trans/builder.rs b/src/librustc_trans/builder.rs
index f64e581c177..a62f07042a7 100644
--- a/src/librustc_trans/builder.rs
+++ b/src/librustc_trans/builder.rs
@@ -1149,6 +1149,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
+    pub fn set_invariant_load(&self, load: ValueRef) {
+        unsafe {
+            llvm::LLVMSetMetadata(load, llvm::MD_invariant_load as c_uint,
+                                  llvm::LLVMMDNodeInContext(self.ccx.llcx(), ptr::null(), 0));
+        }
+    }
+
     /// Returns the ptr value that should be used for storing `val`.
     fn check_store<'b>(&self,
                        val: ValueRef,
@@ -1181,7 +1188,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
 
         assert!(fn_ty.kind() == llvm::TypeKind::Function,
-                "builder::{} not passed a function", typ);
+                "builder::{} not passed a function, but {:?}", typ, fn_ty);
 
         let param_tys = fn_ty.func_params();
 
diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs
index b5f948442b7..83a38a529d0 100644
--- a/src/librustc_trans/collector.rs
+++ b/src/librustc_trans/collector.rs
@@ -489,6 +489,20 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
                                                           self.output);
                 }
             }
+            mir::Rvalue::Cast(mir::CastKind::ClosureFnPointer, ref operand, _) => {
+                let source_ty = operand.ty(self.mir, self.scx.tcx());
+                match source_ty.sty {
+                    ty::TyClosure(def_id, substs) => {
+                        let closure_trans_item =
+                            create_fn_trans_item(self.scx,
+                                                 def_id,
+                                                 substs.substs,
+                                                 self.param_substs);
+                        self.output.push(closure_trans_item);
+                    }
+                    _ => bug!(),
+                }
+            }
             mir::Rvalue::Box(..) => {
                 let exchange_malloc_fn_def_id =
                     self.scx
@@ -615,19 +629,13 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
                                               def_id: DefId)
                                               -> bool {
             match tcx.item_type(def_id).sty {
-                ty::TyFnDef(def_id, _, f) => {
+                ty::TyFnDef(def_id, _, _) => {
                     // Some constructors also have type TyFnDef but they are
                     // always instantiated inline and don't result in a
                     // translation item. Same for FFI functions.
                     if let Some(hir_map::NodeForeignItem(_)) = tcx.hir.get_if_local(def_id) {
                         return false;
                     }
-
-                    if let Some(adt_def) = f.sig.output().skip_binder().ty_adt_def() {
-                        if adt_def.variants.iter().any(|v| def_id == v.did) {
-                            return false;
-                        }
-                    }
                 }
                 ty::TyClosure(..) => {}
                 _ => return false
@@ -689,6 +697,16 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
 fn should_trans_locally<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                   def_id: DefId)
                                   -> bool {
+    if let ty::TyFnDef(_, _, f) = tcx.item_type(def_id).sty {
+        if let Some(adt_def) = f.sig.output().skip_binder().ty_adt_def() {
+            if adt_def.variants.iter().any(|v| def_id == v.did) {
+                // HACK: ADT constructors are translated in-place and
+                // do not have a trans-item.
+                return false;
+            }
+        }
+    }
+
     if def_id.is_local() {
         true
     } else {
diff --git a/src/librustc_trans/glue.rs b/src/librustc_trans/glue.rs
index d66ea4d650f..9963514acd7 100644
--- a/src/librustc_trans/glue.rs
+++ b/src/librustc_trans/glue.rs
@@ -386,7 +386,15 @@ pub fn size_and_align_of_dst<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, t: Ty<'tcx>, inf
             let info = bcx.pointercast(info, Type::int(bcx.ccx).ptr_to());
             let size_ptr = bcx.gepi(info, &[1]);
             let align_ptr = bcx.gepi(info, &[2]);
-            (bcx.load(size_ptr, None), bcx.load(align_ptr, None))
+
+            let size = bcx.load(size_ptr, None);
+            let align = bcx.load(align_ptr, None);
+
+            // Vtable loads are invariant
+            bcx.set_invariant_load(size);
+            bcx.set_invariant_load(align);
+
+            (size, align)
         }
         ty::TySlice(_) | ty::TyStr => {
             let unit_ty = t.sequence_element_type(bcx.tcx());
diff --git a/src/librustc_trans/meth.rs b/src/librustc_trans/meth.rs
index 3033ae61d20..a3f4168e96f 100644
--- a/src/librustc_trans/meth.rs
+++ b/src/librustc_trans/meth.rs
@@ -30,13 +30,15 @@ const VTABLE_OFFSET: usize = 3;
 /// Extracts a method from a trait object's vtable, at the specified index.
 pub fn get_virtual_method<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
                                     llvtable: ValueRef,
-                                    vtable_index: usize)
-                                    -> ValueRef {
+                                    vtable_index: usize) -> ValueRef {
     // Load the data pointer from the object.
     debug!("get_virtual_method(vtable_index={}, llvtable={:?})",
            vtable_index, Value(llvtable));
 
-    bcx.load(bcx.gepi(llvtable, &[vtable_index + VTABLE_OFFSET]), None)
+    let ptr = bcx.load_nonnull(bcx.gepi(llvtable, &[vtable_index + VTABLE_OFFSET]), None);
+    // Vtable loads are invariant
+    bcx.set_invariant_load(ptr);
+    ptr
 }
 
 /// Generate a shim function that allows an object type like `SomeTrait` to
diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs
index 7e17ae5f1d3..e6cae2f9f32 100644
--- a/src/librustc_trans/mir/constant.rs
+++ b/src/librustc_trans/mir/constant.rs
@@ -20,7 +20,7 @@ use rustc::mir;
 use rustc::mir::tcx::LvalueTy;
 use rustc::ty::{self, layout, Ty, TyCtxt, TypeFoldable};
 use rustc::ty::cast::{CastTy, IntTy};
-use rustc::ty::subst::Substs;
+use rustc::ty::subst::{Kind, Substs};
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use {abi, adt, base, Disr, machine};
 use callee::Callee;
@@ -578,6 +578,27 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
                             }
                         }
                     }
+                    mir::CastKind::ClosureFnPointer => {
+                        match operand.ty.sty {
+                            ty::TyClosure(def_id, substs) => {
+                                // Get the def_id for FnOnce::call_once
+                                let fn_once = tcx.lang_items.fn_once_trait().unwrap();
+                                let call_once = tcx
+                                    .global_tcx().associated_items(fn_once)
+                                    .find(|it| it.kind == ty::AssociatedKind::Method)
+                                    .unwrap().def_id;
+                                // Now create its substs [Closure, Tuple]
+                                let input = tcx.closure_type(def_id, substs).sig.input(0);
+                                let substs = tcx.mk_substs([operand.ty, input.skip_binder()]
+                                    .iter().cloned().map(Kind::from));
+                                Callee::def(self.ccx, call_once, substs)
+                                    .reify(self.ccx)
+                            }
+                            _ => {
+                                bug!("{} cannot be cast to a fn ptr", operand.ty)
+                            }
+                        }
+                    }
                     mir::CastKind::UnsafeFnPointer => {
                         // this is a no-op at the LLVM level
                         operand.llval
diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs
index 7d4f542addb..6f6d81a2535 100644
--- a/src/librustc_trans/mir/rvalue.rs
+++ b/src/librustc_trans/mir/rvalue.rs
@@ -12,6 +12,7 @@ use llvm::{self, ValueRef};
 use rustc::ty::{self, Ty};
 use rustc::ty::cast::{CastTy, IntTy};
 use rustc::ty::layout::Layout;
+use rustc::ty::subst::Kind;
 use rustc::mir::tcx::LvalueTy;
 use rustc::mir;
 use middle::lang_items::ExchangeMallocFnLangItem;
@@ -190,6 +191,28 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
                             }
                         }
                     }
+                    mir::CastKind::ClosureFnPointer => {
+                        match operand.ty.sty {
+                            ty::TyClosure(def_id, substs) => {
+                                // Get the def_id for FnOnce::call_once
+                                let fn_once = bcx.tcx().lang_items.fn_once_trait().unwrap();
+                                let call_once = bcx.tcx()
+                                    .global_tcx().associated_items(fn_once)
+                                    .find(|it| it.kind == ty::AssociatedKind::Method)
+                                    .unwrap().def_id;
+                                // Now create its substs [Closure, Tuple]
+                                let input = bcx.tcx().closure_type(def_id, substs).sig.input(0);
+                                let substs = bcx.tcx().mk_substs([operand.ty, input.skip_binder()]
+                                    .iter().cloned().map(Kind::from));
+                                OperandValue::Immediate(
+                                    Callee::def(bcx.ccx, call_once, substs)
+                                        .reify(bcx.ccx))
+                            }
+                            _ => {
+                                bug!("{} cannot be cast to a fn ptr", operand.ty)
+                            }
+                        }
+                    }
                     mir::CastKind::UnsafeFnPointer => {
                         // this is a no-op at the LLVM level
                         operand.val
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 718c273785a..424e3143929 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -63,13 +63,17 @@
 use check::FnCtxt;
 
 use rustc::hir;
+use rustc::hir::def_id::DefId;
 use rustc::infer::{Coercion, InferOk, TypeTrace};
 use rustc::traits::{self, ObligationCause, ObligationCauseCode};
 use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow};
-use rustc::ty::{self, LvaluePreference, TypeAndMut, Ty};
+use rustc::ty::{self, LvaluePreference, TypeAndMut,
+                Ty, ClosureSubsts};
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::error::TypeError;
 use rustc::ty::relate::RelateResult;
+use syntax::abi;
+use syntax::feature_gate;
 use util::common::indent;
 
 use std::cell::RefCell;
@@ -196,6 +200,11 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
                 // unsafe qualifier.
                 self.coerce_from_fn_pointer(a, a_f, b)
             }
+            ty::TyClosure(def_id_a, substs_a) => {
+                // Non-capturing closures are coercible to
+                // function pointers
+                self.coerce_closure_to_fn(a, def_id_a, substs_a, b)
+            }
             _ => {
                 // Otherwise, just use unification rules.
                 self.unify_and_identity(a, b)
@@ -551,6 +560,60 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
         }
     }
 
+    fn coerce_closure_to_fn(&self,
+                           a: Ty<'tcx>,
+                           def_id_a: DefId,
+                           substs_a: ClosureSubsts<'tcx>,
+                           b: Ty<'tcx>)
+                           -> CoerceResult<'tcx> {
+        //! Attempts to coerce from the type of a non-capturing closure
+        //! into a function pointer.
+        //!
+
+        let b = self.shallow_resolve(b);
+
+        let node_id_a = self.tcx.hir.as_local_node_id(def_id_a).unwrap();
+        match b.sty {
+            ty::TyFnPtr(_) if self.tcx.with_freevars(node_id_a, |v| v.is_empty()) => {
+                if !self.tcx.sess.features.borrow().closure_to_fn_coercion {
+                    feature_gate::emit_feature_err(&self.tcx.sess.parse_sess,
+                                                   "closure_to_fn_coercion",
+                                                   self.cause.span,
+                                                   feature_gate::GateIssue::Language,
+                                                   feature_gate::CLOSURE_TO_FN_COERCION);
+                    return self.unify_and_identity(a, b);
+                }
+                // We coerce the closure, which has fn type
+                //     `extern "rust-call" fn((arg0,arg1,...)) -> _`
+                // to
+                //     `fn(arg0,arg1,...) -> _`
+                let sig = self.closure_type(def_id_a, substs_a).sig;
+                let converted_sig = sig.map_bound(|s| {
+                    let params_iter = match s.inputs()[0].sty {
+                        ty::TyTuple(params, _) => {
+                            params.into_iter().cloned()
+                        }
+                        _ => bug!(),
+                    };
+                    self.tcx.mk_fn_sig(params_iter,
+                                       s.output(),
+                                       s.variadic)
+                });
+                let fn_ty = self.tcx.mk_bare_fn(ty::BareFnTy {
+                    unsafety: hir::Unsafety::Normal,
+                    abi: abi::Abi::Rust,
+                    sig: converted_sig,
+                });
+                let pointer_ty = self.tcx.mk_fn_ptr(&fn_ty);
+                debug!("coerce_closure_to_fn(a={:?}, b={:?}, pty={:?})",
+                       a, b, pointer_ty);
+                self.unify_and_identity(pointer_ty, b)
+                    .map(|(ty, _)| (ty, Adjust::ClosureFnPointer))
+            }
+            _ => self.unify_and_identity(a, b),
+        }
+    }
+
     fn coerce_unsafe_ptr(&self,
                          a: Ty<'tcx>,
                          b: Ty<'tcx>,
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 9d963226caf..14dacb0ca97 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -425,15 +425,12 @@ pub struct EnclosingLoops<'gcx, 'tcx> {
 }
 
 impl<'gcx, 'tcx> EnclosingLoops<'gcx, 'tcx> {
-    fn find_loop(&mut self, id: Option<ast::NodeId>) -> Option<&mut LoopCtxt<'gcx, 'tcx>> {
-        if let Some(id) = id {
-            if let Some(ix) = self.by_id.get(&id).cloned() {
-                Some(&mut self.stack[ix])
-            } else {
-                None
-            }
+    fn find_loop(&mut self, id: hir::LoopIdResult) -> Option<&mut LoopCtxt<'gcx, 'tcx>> {
+        let id_res: Result<_,_> = id.into();
+        if let Some(ix) = id_res.ok().and_then(|id| self.by_id.get(&id).cloned()) {
+            Some(&mut self.stack[ix])
         } else {
-            self.stack.last_mut()
+            None
         }
     }
 }
@@ -3596,10 +3593,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
               tcx.mk_nil()
           }
           hir::ExprBreak(label, ref expr_opt) => {
-            let loop_id = label.map(|l| l.loop_id);
             let coerce_to = {
                 let mut enclosing_loops = self.enclosing_loops.borrow_mut();
-                enclosing_loops.find_loop(loop_id).map(|ctxt| ctxt.coerce_to)
+                enclosing_loops.find_loop(label.loop_id).map(|ctxt| ctxt.coerce_to)
             };
             if let Some(coerce_to) = coerce_to {
                 let e_ty;
@@ -3614,8 +3610,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     e_ty = tcx.mk_nil();
                     cause = self.misc(expr.span);
                 }
+
                 let mut enclosing_loops = self.enclosing_loops.borrow_mut();
-                let ctxt = enclosing_loops.find_loop(loop_id).unwrap();
+                let ctxt = enclosing_loops.find_loop(label.loop_id).unwrap();
 
                 let result = if let Some(ref e) = *expr_opt {
                     // Special-case the first element, as it has no "previous expressions".
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index a2922270583..a25e5f3f283 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -412,6 +412,10 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
                         adjustment::Adjust::MutToConstPointer
                     }
 
+                    adjustment::Adjust::ClosureFnPointer => {
+                        adjustment::Adjust::ClosureFnPointer
+                    }
+
                     adjustment::Adjust::UnsafeFnPointer => {
                         adjustment::Adjust::UnsafeFnPointer
                     }
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index 1c37067d7f6..c7000ee1e40 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -12,7 +12,7 @@ use std::env;
 use std::ffi::OsString;
 use std::io::prelude::*;
 use std::io;
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
 use std::panic::{self, AssertUnwindSafe};
 use std::process::Command;
 use std::rc::Rc;
@@ -485,7 +485,15 @@ impl Collector {
 
     pub fn get_filename(&self) -> String {
         if let Some(ref codemap) = self.codemap {
-            codemap.span_to_filename(self.position)
+            let filename = codemap.span_to_filename(self.position);
+            if let Ok(cur_dir) = env::current_dir() {
+                if let Ok(path) = Path::new(&filename).strip_prefix(&cur_dir) {
+                    if let Some(path) = path.to_str() {
+                        return path.to_owned();
+                    }
+                }
+            }
+            filename
         } else if let Some(ref filename) = self.filename {
             filename.clone()
         } else {
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 394eb477989..64f37925a98 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -199,7 +199,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         self.inside_public_path = orig_inside_public_path;
         if let Some(exports) = self.cx.export_map.get(&id) {
             for export in exports {
-                if let Def::Macro(def_id) = export.def {
+                if let Def::Macro(def_id, ..) = export.def {
                     if def_id.krate == LOCAL_CRATE {
                         continue // These are `krate.exported_macros`, handled in `self.visit()`.
                     }
diff --git a/src/libstd/build.rs b/src/libstd/build.rs
index 0fca374f6e6..038dea77f3e 100644
--- a/src/libstd/build.rs
+++ b/src/libstd/build.rs
@@ -59,6 +59,10 @@ fn main() {
         println!("cargo:rustc-link-lib=userenv");
         println!("cargo:rustc-link-lib=shell32");
     } else if target.contains("fuchsia") {
+        // use system-provided libbacktrace
+        if cfg!(feature = "backtrace") {
+            println!("cargo:rustc-link-lib=backtrace");
+        }
         println!("cargo:rustc-link-lib=magenta");
         println!("cargo:rustc-link-lib=mxio");
         println!("cargo:rustc-link-lib=launchpad"); // for std::process
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index fd5827b4c07..f0738fe9b70 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -182,12 +182,12 @@ impl DefaultResizePolicy {
 // ----------------------
 // To protect against degenerate performance scenarios (including DOS attacks),
 // the implementation includes an adaptive behavior that can resize the map
-// early (before its capacity is exceeded) when suspiciously long probe or
-// forward shifts sequences are encountered.
+// early (before its capacity is exceeded) when suspiciously long probe sequences
+// are encountered.
 //
 // With this algorithm in place it would be possible to turn a CPU attack into
 // a memory attack due to the aggressive resizing. To prevent that the
-// adaptive behavior only triggers when the map occupancy is half the maximum occupancy.
+// adaptive behavior only triggers when the map is at least half full.
 // This reduces the effectiveness of the algorithm but also makes it completely safe.
 //
 // The previous safety measure also prevents degenerate interactions with
@@ -195,16 +195,11 @@ impl DefaultResizePolicy {
 // DOS attack.
 //
 const DISPLACEMENT_THRESHOLD: usize = 128;
-const FORWARD_SHIFT_THRESHOLD: usize = 512;
 //
-// The thresholds of 128 and 512 are chosen to minimize the chance of exceeding them.
+// The threshold of 128 is chosen to minimize the chance of exceeding it.
 // In particular, we want that chance to be less than 10^-8 with a load of 90%.
 // For displacement, the smallest constant that fits our needs is 90,
-// so we round that up to 128. For the number of forward-shifted buckets,
-// we choose k=512. Keep in mind that the run length is a sum of the displacement and
-// the number of forward-shifted buckets, so its threshold is 128+512=640.
-// Even though the probability of having a run length of more than 640 buckets may be
-// higher than the probability we want, it should be low enough.
+// so we round that up to 128.
 //
 // At a load factor of α, the odds of finding the target bucket after exactly n
 // unsuccesful probes[1] are
@@ -212,16 +207,12 @@ const FORWARD_SHIFT_THRESHOLD: usize = 512;
 // Pr_α{displacement = n} =
 // (1 - α) / α * ∑_{k≥1} e^(-kα) * (kα)^(k+n) / (k + n)! * (1 - kα / (k + n + 1))
 //
-// We use this formula to find the probability of loading half of triggering the adaptive behavior
+// We use this formula to find the probability of triggering the adaptive behavior
 //
 // Pr_0.909{displacement > 128} = 1.601 * 10^-11
 //
-// FIXME: Extend with math for shift threshold in [2]
-//
 // 1. Alfredo Viola (2005). Distributional analysis of Robin Hood linear probing
 //    hashing with buckets.
-// 2. http://www.cs.tau.ac.il/~zwick/Adv-Alg-2015/Linear-Probing.pdf
-
 
 /// A hash map implementation which uses linear probing with Robin Hood bucket
 /// stealing.
@@ -494,7 +485,7 @@ fn robin_hood<'a, K: 'a, V: 'a>(bucket: FullBucketMut<'a, K, V>,
                                 mut hash: SafeHash,
                                 mut key: K,
                                 mut val: V)
-                                -> (usize, &'a mut V) {
+                                -> &'a mut V {
     let start_index = bucket.index();
     let size = bucket.table().size();
     // Save the *starting point*.
@@ -519,7 +510,6 @@ fn robin_hood<'a, K: 'a, V: 'a>(bucket: FullBucketMut<'a, K, V>,
                 Empty(bucket) => {
                     // Found a hole!
                     let bucket = bucket.put(hash, key, val);
-                    let end_index = bucket.index();
                     // Now that it's stolen, just read the value's pointer
                     // right out of the table! Go back to the *starting point*.
                     //
@@ -527,7 +517,7 @@ fn robin_hood<'a, K: 'a, V: 'a>(bucket: FullBucketMut<'a, K, V>,
                     // bucket, which is a FullBucket on top of a
                     // FullBucketMut, into just one FullBucketMut. The "table"
                     // refers to the inner FullBucketMut in this context.
-                    return (end_index - start_index, bucket.into_table().into_mut_refs().1);
+                    return bucket.into_table().into_mut_refs().1;
                 }
                 Full(bucket) => bucket,
             };
@@ -2128,18 +2118,16 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> {
     pub fn insert(self, value: V) -> &'a mut V {
         match self.elem {
             NeqElem(bucket, disp) => {
-                let (shift, v_ref) = robin_hood(bucket, disp, self.hash, self.key, value);
-                if disp >= DISPLACEMENT_THRESHOLD || shift >= FORWARD_SHIFT_THRESHOLD {
+                if disp >= DISPLACEMENT_THRESHOLD {
                     *self.long_probes = true;
                 }
-                v_ref
+                robin_hood(bucket, disp, self.hash, self.key, value)
             },
             NoElem(bucket, disp) => {
                 if disp >= DISPLACEMENT_THRESHOLD {
                     *self.long_probes = true;
                 }
-                let bucket = bucket.put(self.hash, self.key, value);
-                bucket.into_mut_refs().1
+                bucket.put(self.hash, self.key, value).into_mut_refs().1
             },
         }
     }
diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs
index ac0d0d2afb8..f99634ecac2 100644
--- a/src/libstd/panic.rs
+++ b/src/libstd/panic.rs
@@ -198,7 +198,7 @@ impl<T: RefUnwindSafe + ?Sized> UnwindSafe for *const T {}
 #[stable(feature = "catch_unwind", since = "1.9.0")]
 impl<T: RefUnwindSafe + ?Sized> UnwindSafe for *mut T {}
 #[unstable(feature = "unique", issue = "27730")]
-impl<T: UnwindSafe> UnwindSafe for Unique<T> {}
+impl<T: UnwindSafe + ?Sized> UnwindSafe for Unique<T> {}
 #[unstable(feature = "shared", issue = "27730")]
 impl<T: RefUnwindSafe + ?Sized> UnwindSafe for Shared<T> {}
 #[stable(feature = "catch_unwind", since = "1.9.0")]
diff --git a/src/libstd/sys/redox/mod.rs b/src/libstd/sys/redox/mod.rs
index 5982bdd6549..31c40ea58b1 100644
--- a/src/libstd/sys/redox/mod.rs
+++ b/src/libstd/sys/redox/mod.rs
@@ -13,7 +13,7 @@
 use io::{self, ErrorKind};
 
 pub mod args;
-#[cfg(any(not(cargobuild), feature = "backtrace"))]
+#[cfg(feature = "backtrace")]
 pub mod backtrace;
 pub mod condvar;
 pub mod env;
diff --git a/src/libstd/sys/redox/net/tcp.rs b/src/libstd/sys/redox/net/tcp.rs
index a3f202ccd97..936097d7fb2 100644
--- a/src/libstd/sys/redox/net/tcp.rs
+++ b/src/libstd/sys/redox/net/tcp.rs
@@ -63,6 +63,10 @@ impl TcpStream {
         Ok(path_to_local_addr(path.to_str().unwrap_or("")))
     }
 
+    pub fn peek(&self, _buf: &mut [u8]) -> Result<usize> {
+        Err(Error::new(ErrorKind::Other, "TcpStream::peek not implemented"))
+    }
+
     pub fn shutdown(&self, _how: Shutdown) -> Result<()> {
         Err(Error::new(ErrorKind::Other, "TcpStream::shutdown not implemented"))
     }
diff --git a/src/libstd/sys/redox/net/udp.rs b/src/libstd/sys/redox/net/udp.rs
index 36f0819d308..93ebcc95fd0 100644
--- a/src/libstd/sys/redox/net/udp.rs
+++ b/src/libstd/sys/redox/net/udp.rs
@@ -87,6 +87,14 @@ impl UdpSocket {
         Ok(path_to_local_addr(path.to_str().unwrap_or("")))
     }
 
+    pub fn peek(&self, _buf: &mut [u8]) -> Result<usize> {
+        Err(Error::new(ErrorKind::Other, "UdpSocket::peek not implemented"))
+    }
+
+    pub fn peek_from(&self, _buf: &mut [u8]) -> Result<(usize, SocketAddr)> {
+        Err(Error::new(ErrorKind::Other, "UdpSocket::peek_from not implemented"))
+    }
+
     pub fn broadcast(&self) -> Result<bool> {
         Err(Error::new(ErrorKind::Other, "UdpSocket::broadcast not implemented"))
     }
diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs
index 8b5c0c04276..d0fb96b1ff1 100644
--- a/src/libstd/sys/unix/fs.rs
+++ b/src/libstd/sys/unix/fs.rs
@@ -35,7 +35,8 @@ use libc::{stat as stat64, fstat as fstat64, lstat as lstat64, off_t as off64_t,
            ftruncate as ftruncate64, lseek as lseek64, dirent as dirent64, open as open64};
 #[cfg(not(any(target_os = "linux",
               target_os = "emscripten",
-              target_os = "solaris")))]
+              target_os = "solaris",
+              target_os = "fuchsia")))]
 use libc::{readdir_r as readdir64_r};
 
 pub struct File(FileDesc);
@@ -59,10 +60,10 @@ pub struct DirEntry {
     entry: dirent64,
     root: Arc<PathBuf>,
     // We need to store an owned copy of the directory name
-    // on Solaris because a) it uses a zero-length array to
-    // store the name, b) its lifetime between readdir calls
-    // is not guaranteed.
-    #[cfg(target_os = "solaris")]
+    // on Solaris and Fuchsia because a) it uses a zero-length
+    // array to store the name, b) its lifetime between readdir
+    // calls is not guaranteed.
+    #[cfg(any(target_os = "solaris", target_os = "fuchsia"))]
     name: Box<[u8]>
 }
 
@@ -205,14 +206,14 @@ impl fmt::Debug for ReadDir {
 impl Iterator for ReadDir {
     type Item = io::Result<DirEntry>;
 
-    #[cfg(target_os = "solaris")]
+    #[cfg(any(target_os = "solaris", target_os = "fuchsia"))]
     fn next(&mut self) -> Option<io::Result<DirEntry>> {
         unsafe {
             loop {
                 // Although readdir_r(3) would be a correct function to use here because
-                // of the thread safety, on Illumos the readdir(3C) function is safe to use
-                // in threaded applications and it is generally preferred over the
-                // readdir_r(3C) function.
+                // of the thread safety, on Illumos and Fuchsia the readdir(3C) function
+                // is safe to use in threaded applications and it is generally preferred
+                // over the readdir_r(3C) function.
                 super::os::set_errno(0);
                 let entry_ptr = libc::readdir(self.dirp.0);
                 if entry_ptr.is_null() {
@@ -240,7 +241,7 @@ impl Iterator for ReadDir {
         }
     }
 
-    #[cfg(not(target_os = "solaris"))]
+    #[cfg(not(any(target_os = "solaris", target_os = "fuchsia")))]
     fn next(&mut self) -> Option<io::Result<DirEntry>> {
         unsafe {
             let mut ret = DirEntry {
@@ -344,14 +345,14 @@ impl DirEntry {
     #[cfg(any(target_os = "android",
               target_os = "linux",
               target_os = "emscripten",
-              target_os = "haiku",
-              target_os = "fuchsia"))]
+              target_os = "haiku"))]
     fn name_bytes(&self) -> &[u8] {
         unsafe {
             CStr::from_ptr(self.entry.d_name.as_ptr()).to_bytes()
         }
     }
-    #[cfg(target_os = "solaris")]
+    #[cfg(any(target_os = "solaris",
+              target_os = "fuchsia"))]
     fn name_bytes(&self) -> &[u8] {
         &*self.name
     }
diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs
index e78928c2667..36928696c40 100644
--- a/src/libstd/sys/unix/os.rs
+++ b/src/libstd/sys/unix/os.rs
@@ -64,7 +64,7 @@ pub fn errno() -> i32 {
 }
 
 /// Sets the platform-specific value of errno
-#[cfg(target_os = "solaris")] // only needed for readdir so far
+#[cfg(any(target_os = "solaris", target_os = "fuchsia"))] // only needed for readdir so far
 pub fn set_errno(e: i32) {
     unsafe {
         *errno_location() = e as c_int
diff --git a/src/libstd/sys/unix/process/magenta.rs b/src/libstd/sys/unix/process/magenta.rs
index a81bedcad22..08a827ce081 100644
--- a/src/libstd/sys/unix/process/magenta.rs
+++ b/src/libstd/sys/unix/process/magenta.rs
@@ -111,7 +111,7 @@ extern {
     pub fn mx_handle_duplicate(handle: mx_handle_t, rights: mx_rights_t,
                                out: *const mx_handle_t) -> mx_handle_t;
 
-    pub fn mx_handle_wait_one(handle: mx_handle_t, signals: mx_signals_t, timeout: mx_time_t,
+    pub fn mx_object_wait_one(handle: mx_handle_t, signals: mx_signals_t, timeout: mx_time_t,
                               pending: *mut mx_signals_t) -> mx_status_t;
 
     pub fn mx_object_get_info(handle: mx_handle_t, topic: u32, buffer: *mut c_void,
diff --git a/src/libstd/sys/unix/process/process_fuchsia.rs b/src/libstd/sys/unix/process/process_fuchsia.rs
index 0bb2e0c1a83..608e44ca9e8 100644
--- a/src/libstd/sys/unix/process/process_fuchsia.rs
+++ b/src/libstd/sys/unix/process/process_fuchsia.rs
@@ -151,7 +151,7 @@ impl Process {
         let mut avail: mx_size_t = 0;
 
         unsafe {
-            mx_cvt(mx_handle_wait_one(self.handle.raw(), MX_TASK_TERMINATED,
+            mx_cvt(mx_object_wait_one(self.handle.raw(), MX_TASK_TERMINATED,
                                       MX_TIME_INFINITE, ptr::null_mut()))?;
             mx_cvt(mx_object_get_info(self.handle.raw(), MX_INFO_PROCESS,
                                       &mut proc_info as *mut _ as *mut libc::c_void,
@@ -174,7 +174,7 @@ impl Process {
         let mut avail: mx_size_t = 0;
 
         unsafe {
-            let status = mx_handle_wait_one(self.handle.raw(), MX_TASK_TERMINATED,
+            let status = mx_object_wait_one(self.handle.raw(), MX_TASK_TERMINATED,
                                             0, ptr::null_mut());
             match status {
                 0 => { }, // Success
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index b61ab74687b..666e2205b4a 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -475,7 +475,7 @@ pub type BuiltinDeriveFn =
     for<'cx> fn(&'cx mut ExtCtxt, Span, &MetaItem, &Annotatable, &mut FnMut(Annotatable));
 
 /// Represents different kinds of macro invocations that can be resolved.
-#[derive(Clone, Copy, PartialEq, Eq)]
+#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum MacroKind {
     /// A bang macro - foo!()
     Bang,
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index b7be084fa0b..c2b72edb66c 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -200,9 +200,6 @@ declare_features! (
     // rustc internal
     (active, prelude_import, "1.2.0", None),
 
-    // Allows the definition recursive static items.
-    (active, static_recursion, "1.3.0", Some(29719)),
-
     // Allows default type parameters to influence type inference.
     (active, default_type_parameter_fallback, "1.3.0", Some(27336)),
 
@@ -328,6 +325,10 @@ declare_features! (
 
     // Used to identify crates that contain sanitizer runtimes
     // rustc internal
+    (active, closure_to_fn_coercion, "1.17.0", Some(39817)),
+
+    // Used to identify crates that contain sanitizer runtimes
+    // rustc internal
     (active, sanitizer_runtime, "1.17.0", None),
 );
 
@@ -387,6 +388,8 @@ declare_features! (
     (accepted, static_in_const, "1.17.0", Some(35897)),
     // Allows field shorthands (`x` meaning `x: x`) in struct literal expressions.
     (accepted, field_init_shorthand, "1.17.0", Some(37340)),
+    // Allows the definition recursive static items.
+    (accepted, static_recursion, "1.17.0", Some(29719)),
 );
 // If you change this, please modify src/doc/unstable-book as well. You must
 // move that documentation into the relevant place in the other docs, and
@@ -982,6 +985,9 @@ pub const EXPLAIN_DERIVE_UNDERSCORE: &'static str =
 pub const EXPLAIN_PLACEMENT_IN: &'static str =
     "placement-in expression syntax is experimental and subject to change.";
 
+pub const CLOSURE_TO_FN_COERCION: &'static str =
+    "non-capturing closure to fn coercion is experimental";
+
 struct PostExpansionVisitor<'a> {
     context: &'a Context<'a>,
 }
diff --git a/COMPILER_TESTS.md b/src/test/COMPILER_TESTS.md
index 58df1aae6d3..58df1aae6d3 100644
--- a/COMPILER_TESTS.md
+++ b/src/test/COMPILER_TESTS.md
diff --git a/src/test/codegen/function-arguments.rs b/src/test/codegen/function-arguments.rs
index c373cdb76c5..76313b158ab 100644
--- a/src/test/codegen/function-arguments.rs
+++ b/src/test/codegen/function-arguments.rs
@@ -121,13 +121,13 @@ pub fn unsafe_slice(_: &[UnsafeInner]) {
 fn str(_: &[u8]) {
 }
 
-// CHECK: @trait_borrow(i8* nonnull, void (i8*)** nonnull)
+// CHECK: @trait_borrow(i8* nonnull, void (i8*)** noalias nonnull readonly)
 // FIXME #25759 This should also have `nocapture`
 #[no_mangle]
 fn trait_borrow(_: &Drop) {
 }
 
-// CHECK: @trait_box(i8* noalias nonnull, void (i8*)** nonnull)
+// CHECK: @trait_box(i8* noalias nonnull, void (i8*)** noalias nonnull readonly)
 #[no_mangle]
 fn trait_box(_: Box<Drop>) {
 }
diff --git a/src/test/compile-fail-fulldeps/proc-macro/resolve-error.rs b/src/test/compile-fail-fulldeps/proc-macro/resolve-error.rs
index c9a36920a19..eac0be6f848 100644
--- a/src/test/compile-fail-fulldeps/proc-macro/resolve-error.rs
+++ b/src/test/compile-fail-fulldeps/proc-macro/resolve-error.rs
@@ -22,15 +22,24 @@ extern crate attr_proc_macro;
 
 use attr_proc_macro::attr_proc_macro;
 
-#[derive(FooWithLongNam)]
-//~^ ERROR cannot find derive macro `FooWithLongNam` in this scope
+macro_rules! FooWithLongNam {
+    () => {}
+}
+
+#[derive(FooWithLongNan)]
+//~^ ERROR cannot find derive macro `FooWithLongNan` in this scope
 //~^^ HELP did you mean `FooWithLongName`?
 struct Foo;
 
 #[attr_proc_macra]
 //~^ ERROR cannot find attribute macro `attr_proc_macra` in this scope
+//~^^ HELP did you mean `attr_proc_macro`?
 struct Bar;
 
+#[FooWithLongNan]
+//~^ ERROR cannot find attribute macro `FooWithLongNan` in this scope
+struct Asdf;
+
 #[derive(Dlone)]
 //~^ ERROR cannot find derive macro `Dlone` in this scope
 //~^^ HELP did you mean `Clone`?
@@ -41,4 +50,18 @@ struct A;
 //~^^ HELP did you mean `Clona`?
 struct B;
 
-fn main() {}
+#[derive(attr_proc_macra)]
+//~^ ERROR cannot find derive macro `attr_proc_macra` in this scope
+struct C;
+
+fn main() {
+    FooWithLongNama!();
+    //~^ ERROR cannot find macro `FooWithLongNama!` in this scope
+    //~^^ HELP did you mean `FooWithLongNam!`?
+
+    attr_proc_macra!();
+    //~^ ERROR cannot find macro `attr_proc_macra!` in this scope
+
+    Dlona!();
+    //~^ ERROR cannot find macro `Dlona!` in this scope
+}
diff --git a/src/test/compile-fail/asm-bad-clobber.rs b/src/test/compile-fail/asm-bad-clobber.rs
index cb931329051..145662fd87c 100644
--- a/src/test/compile-fail/asm-bad-clobber.rs
+++ b/src/test/compile-fail/asm-bad-clobber.rs
@@ -13,6 +13,7 @@
 // ignore-aarch64
 // ignore-s390x
 // ignore-emscripten
+// ignore-powerpc
 
 #![feature(asm, rustc_attrs)]
 
diff --git a/src/test/compile-fail/asm-in-bad-modifier.rs b/src/test/compile-fail/asm-in-bad-modifier.rs
index 7ba5beac213..f0467e75223 100644
--- a/src/test/compile-fail/asm-in-bad-modifier.rs
+++ b/src/test/compile-fail/asm-in-bad-modifier.rs
@@ -10,6 +10,7 @@
 
 // ignore-s390x
 // ignore-emscripten
+// ignore-powerpc
 
 #![feature(asm)]
 
diff --git a/src/test/compile-fail/asm-misplaced-option.rs b/src/test/compile-fail/asm-misplaced-option.rs
index bafbf625e35..37a26753531 100644
--- a/src/test/compile-fail/asm-misplaced-option.rs
+++ b/src/test/compile-fail/asm-misplaced-option.rs
@@ -13,6 +13,7 @@
 // ignore-aarch64
 // ignore-s390x
 // ignore-emscripten
+// ignore-powerpc
 
 #![feature(asm, rustc_attrs)]
 
diff --git a/src/test/compile-fail/asm-out-assign-imm.rs b/src/test/compile-fail/asm-out-assign-imm.rs
index 161c0b977ff..3c4a5dcb7b0 100644
--- a/src/test/compile-fail/asm-out-assign-imm.rs
+++ b/src/test/compile-fail/asm-out-assign-imm.rs
@@ -10,6 +10,7 @@
 
 // ignore-s390x
 // ignore-emscripten
+// ignore-powerpc
 
 #![feature(asm)]
 
diff --git a/src/test/compile-fail/asm-out-no-modifier.rs b/src/test/compile-fail/asm-out-no-modifier.rs
index cb8fb19a7c7..acf575c003a 100644
--- a/src/test/compile-fail/asm-out-no-modifier.rs
+++ b/src/test/compile-fail/asm-out-no-modifier.rs
@@ -10,6 +10,7 @@
 
 // ignore-s390x
 // ignore-emscripten
+// ignore-powerpc
 
 #![feature(asm)]
 
diff --git a/src/test/compile-fail/asm-out-read-uninit.rs b/src/test/compile-fail/asm-out-read-uninit.rs
index 42bff4c633a..bd180f6e5eb 100644
--- a/src/test/compile-fail/asm-out-read-uninit.rs
+++ b/src/test/compile-fail/asm-out-read-uninit.rs
@@ -10,6 +10,7 @@
 
 // ignore-s390x
 // ignore-emscripten
+// ignore-powerpc
 
 #![feature(asm)]
 
diff --git a/src/test/compile-fail/closure-no-fn.rs b/src/test/compile-fail/closure-no-fn.rs
new file mode 100644
index 00000000000..fe179e8a48f
--- /dev/null
+++ b/src/test/compile-fail/closure-no-fn.rs
@@ -0,0 +1,24 @@
+// Copyright 2017 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.
+
+// Ensure that capturing closures are never coerced to fns
+// Especially interesting as non-capturing closures can be.
+
+fn main() {
+    let mut a = 0u8;
+    let foo: fn(u8) -> u8 = |v: u8| { a += v; a };
+    //~^ ERROR mismatched types
+    let b = 0u8;
+    let bar: fn() -> u8 = || { b };
+    //~^ ERROR mismatched types
+    let baz: fn() -> u8 = || { b } as fn() -> u8;
+    //~^ ERROR mismatched types
+    //~^^ ERROR non-scalar cast
+}
diff --git a/src/test/compile-fail/default_ty_param_conflict.rs b/src/test/compile-fail/default_ty_param_conflict.rs
index 4702b504f15..8cde239ca6e 100644
--- a/src/test/compile-fail/default_ty_param_conflict.rs
+++ b/src/test/compile-fail/default_ty_param_conflict.rs
@@ -23,8 +23,6 @@ fn main() {
     // Here, F is instantiated with $0=uint
     let x = foo();
     //~^ ERROR: mismatched types
-    //~| expected type `usize`
-    //~| found type `isize`
     //~| NOTE: conflicting type parameter defaults `usize` and `isize`
     //~| NOTE: conflicting type parameter defaults `usize` and `isize`
     //~| NOTE: ...that was applied to an unconstrained type variable here
diff --git a/src/test/compile-fail/default_ty_param_conflict_cross_crate.rs b/src/test/compile-fail/default_ty_param_conflict_cross_crate.rs
index b608c6c99be..e5b035e50aa 100644
--- a/src/test/compile-fail/default_ty_param_conflict_cross_crate.rs
+++ b/src/test/compile-fail/default_ty_param_conflict_cross_crate.rs
@@ -29,6 +29,4 @@ fn main() {
     //~| NOTE: conflicting type parameter defaults `bool` and `char`
     //~| a second default is defined on `default_param_test::bleh`
     //~| NOTE:  ...that was applied to an unconstrained type variable here
-    //~| expected type `bool`
-    //~| found type `char`
 }
diff --git a/src/test/compile-fail/feature-gate-closure_to_fn_coercion.rs b/src/test/compile-fail/feature-gate-closure_to_fn_coercion.rs
new file mode 100644
index 00000000000..d074a35628e
--- /dev/null
+++ b/src/test/compile-fail/feature-gate-closure_to_fn_coercion.rs
@@ -0,0 +1,45 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-stage0: new feature, remove this when SNAP
+// revisions: a b
+
+#[cfg(a)]
+mod a {
+    const FOO: fn(u8) -> u8 = |v: u8| { v };
+    //[a]~^ ERROR non-capturing closure to fn coercion is experimental
+    //[a]~^^ ERROR mismatched types
+
+    const BAR: [fn(&mut u32); 1] = [
+        |v: &mut u32| *v += 1,
+    //[a]~^ ERROR non-capturing closure to fn coercion is experimental
+    //[a]~^^ ERROR mismatched types
+    ];
+}
+
+#[cfg(b)]
+mod b {
+    fn func_specific() -> (fn() -> u32) {
+        || return 42
+        //[b]~^ ERROR non-capturing closure to fn coercion is experimental
+        //[b]~^^ ERROR mismatched types
+    }
+    fn foo() {
+        // Items
+        assert_eq!(func_specific()(), 42);
+        let foo: fn(u8) -> u8 = |v: u8| { v };
+        //[b]~^ ERROR non-capturing closure to fn coercion is experimental
+        //[b]~^^ ERROR mismatched types
+    }
+
+}
+
+
+
diff --git a/src/test/compile-fail/feature-gate-static_recursion.rs b/src/test/compile-fail/feature-gate-static_recursion.rs
deleted file mode 100644
index bd20c891d8e..00000000000
--- a/src/test/compile-fail/feature-gate-static_recursion.rs
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-static mut S: *const u8 = unsafe { &S as *const *const u8 as *const u8 };
-//~^ ERROR recursive static (see issue #29719)
-
-struct StaticDoubleLinked {
-    prev: &'static StaticDoubleLinked,
-    next: &'static StaticDoubleLinked,
-    data: i32,
-    head: bool,
-}
-
-static L1: StaticDoubleLinked = StaticDoubleLinked{prev: &L3, next: &L2, data: 1, head: true};
-//~^ ERROR recursive static (see issue #29719)
-//~^^ ERROR recursive static (see issue #29719)
-//~^^^ ERROR recursive static (see issue #29719)
-static L2: StaticDoubleLinked = StaticDoubleLinked{prev: &L1, next: &L3, data: 2, head: false};
-static L3: StaticDoubleLinked = StaticDoubleLinked{prev: &L2, next: &L1, data: 3, head: false};
-
-
-pub fn main() {
-    unsafe { assert_eq!(S, *(S as *const *const u8)); }
-
-    let mut test_vec = Vec::new();
-    let mut cur = &L1;
-    loop {
-        test_vec.push(cur.data);
-        cur = cur.next;
-        if cur.head { break }
-    }
-    assert_eq!(&test_vec, &[1,2,3]);
-
-    let mut test_vec = Vec::new();
-    let mut cur = &L1;
-    loop {
-        cur = cur.prev;
-        test_vec.push(cur.data);
-        if cur.head { break }
-    }
-    assert_eq!(&test_vec, &[3,2,1]);
-}
diff --git a/src/test/compile-fail/issue-3008-2.rs b/src/test/compile-fail/issue-3008-2.rs
index 38b5fcbb3db..3bc8413cbca 100644
--- a/src/test/compile-fail/issue-3008-2.rs
+++ b/src/test/compile-fail/issue-3008-2.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(static_recursion)]
-
 enum foo { foo_(bar) }
 struct bar { x: bar }
 //~^ ERROR E0072
diff --git a/src/test/compile-fail/issue-35869.rs b/src/test/compile-fail/issue-35869.rs
index 8b7fc80bdb6..d1d6390cce3 100644
--- a/src/test/compile-fail/issue-35869.rs
+++ b/src/test/compile-fail/issue-35869.rs
@@ -23,15 +23,19 @@ impl Foo for Bar {
     fn foo(_: fn(u16) -> ()) {}
     //~^ ERROR method `foo` has an incompatible type for trait
     //~| NOTE expected u8
+    //~| NOTE expected type `fn(fn(u8))`
     fn bar(_: Option<u16>) {}
     //~^ ERROR method `bar` has an incompatible type for trait
     //~| NOTE expected u8
+    //~| NOTE expected type `fn(std::option::Option<u8>)`
     fn baz(_: (u16, u16)) {}
     //~^ ERROR method `baz` has an incompatible type for trait
     //~| NOTE expected u8
+    //~| NOTE expected type `fn((u8, u16))`
     fn qux() -> u16 { 5u16 }
     //~^ ERROR method `qux` has an incompatible type for trait
     //~| NOTE expected u8
+    //~| NOTE expected type `fn() -> u8`
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/issue-37131.rs b/src/test/compile-fail/issue-37131.rs
index 88c6eb7f515..efb0b249a8a 100644
--- a/src/test/compile-fail/issue-37131.rs
+++ b/src/test/compile-fail/issue-37131.rs
@@ -11,8 +11,8 @@
 // Tests that compiling for a target which is not installed will result in a helpful
 // error message.
 
-// compile-flags: --target=s390x-unknown-linux-gnu
-// ignore s390x
+// compile-flags: --target=thumbv6m-none-eabi
+// ignore-arm
 
 // error-pattern:target may not be installed
 fn main() { }
diff --git a/src/test/compile-fail/issue-37576.rs b/src/test/compile-fail/issue-37576.rs
new file mode 100644
index 00000000000..e3c1ada878d
--- /dev/null
+++ b/src/test/compile-fail/issue-37576.rs
@@ -0,0 +1,55 @@
+// Copyright 2012 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() {
+    'test_1: while break 'test_1 {}
+    while break {}
+    //~^ ERROR `break` or `continue` with no label
+
+    'test_2: while let true = break 'test_2 {}
+    while let true = break {}
+    //~^ ERROR `break` or `continue` with no label
+
+    loop { 'test_3: while break 'test_3 {} }
+    loop { while break {} }
+    //~^ ERROR `break` or `continue` with no label
+
+    loop {
+        'test_4: while break 'test_4 {}
+        break;
+    }
+    loop {
+        while break {}
+        //~^ ERROR `break` or `continue` with no label
+        break;
+    }
+
+    'test_5: while continue 'test_5 {}
+    while continue {}
+    //~^ ERROR `break` or `continue` with no label
+
+    'test_6: while let true = continue 'test_6 {}
+    while let true = continue {}
+    //~^ ERROR `break` or `continue` with no label
+
+    loop { 'test_7: while continue 'test_7 {} }
+    loop { while continue {} }
+    //~^ ERROR `break` or `continue` with no label
+
+    loop {
+        'test_8: while continue 'test_8 {}
+        continue;
+    }
+    loop {
+        while continue {}
+        //~^ ERROR `break` or `continue` with no label
+        continue;
+    }
+}
diff --git a/src/test/compile-fail/match-privately-empty.rs b/src/test/compile-fail/match-privately-empty.rs
new file mode 100644
index 00000000000..3affb1c03e9
--- /dev/null
+++ b/src/test/compile-fail/match-privately-empty.rs
@@ -0,0 +1,30 @@
+// Copyright 2017 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(never_type)]
+
+mod private {
+    pub struct Private {
+        _bot: !,
+        pub misc: bool,
+    }
+    pub const DATA: Option<Private> = None;
+}
+
+fn main() {
+    match private::DATA {
+    //~^ ERROR non-exhaustive patterns: `Some(Private { misc: true, .. })` not covered
+        None => {}
+        Some(private::Private {
+            misc: false,
+            ..
+        }) => {}
+    }
+}
diff --git a/src/test/compile-fail/resolve-label.rs b/src/test/compile-fail/resolve-label.rs
index ed2c3e0e9b8..6695e972f33 100644
--- a/src/test/compile-fail/resolve-label.rs
+++ b/src/test/compile-fail/resolve-label.rs
@@ -17,8 +17,7 @@ fn f() {
         }
     }
 
-    // issue #37353
-    loop { 'w: while break 'w { } } //~ ERROR use of undeclared label
+    loop { 'w: while break 'w { } }
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/uninhabited-matches-feature-gated.rs b/src/test/compile-fail/uninhabited-matches-feature-gated.rs
index 0f8b0a6c238..0c3ea53a903 100644
--- a/src/test/compile-fail/uninhabited-matches-feature-gated.rs
+++ b/src/test/compile-fail/uninhabited-matches-feature-gated.rs
@@ -19,16 +19,13 @@ fn main() {
     };
 
     let x: &Void = unsafe { std::mem::uninitialized() };
-    let _ = match x {};
-    //~^ ERROR non-exhaustive
+    let _ = match x {}; //~ ERROR non-exhaustive
 
     let x: (Void,) = unsafe { std::mem::uninitialized() };
-    let _ = match x {};
-    //~^ ERROR non-exhaustive
+    let _ = match x {}; //~ ERROR non-exhaustive
 
     let x: [Void; 1] = unsafe { std::mem::uninitialized() };
-    let _ = match x {};
-    //~^ ERROR non-exhaustive
+    let _ = match x {}; //~ ERROR non-exhaustive
 
     let x: &[Void] = unsafe { std::mem::uninitialized() };
     let _ = match x {   //~ ERROR non-exhaustive
@@ -47,4 +44,3 @@ fn main() {
     let Ok(x) = x;
     //~^ ERROR refutable
 }
-
diff --git a/src/test/incremental/issue-39828/auxiliary/generic.rs b/src/test/incremental/issue-39828/auxiliary/generic.rs
new file mode 100644
index 00000000000..a562eab1768
--- /dev/null
+++ b/src/test/incremental/issue-39828/auxiliary/generic.rs
@@ -0,0 +1,18 @@
+// 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.
+
+// revisions:rpass1 rpass2
+// compile-flags: -Z query-dep-graph
+
+#![rustc_partition_reused(module="__rustc_fallback_codegen_unit", cfg="rpass2")]
+#![feature(rustc_attrs)]
+
+#![crate_type="rlib"]
+pub fn foo<T>() { }
diff --git a/src/test/incremental/issue-39828/issue-39828.rs b/src/test/incremental/issue-39828/issue-39828.rs
new file mode 100644
index 00000000000..c729380bd5a
--- /dev/null
+++ b/src/test/incremental/issue-39828/issue-39828.rs
@@ -0,0 +1,22 @@
+// 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.
+
+// Regression test for #39828. If you make use of a module that
+// consists only of generics, no code is generated, just a dummy
+// module. The reduced graph consists of a single node (for that
+// module) with no inputs. Since we only serialize edges, when we
+// reload, we would consider that node dirty since it is not recreated
+// (it is not the target of any edges).
+
+// revisions:rpass1 rpass2
+// aux-build:generic.rs
+
+extern crate generic;
+fn main() { }
diff --git a/src/test/parse-fail/range_inclusive_gate.rs b/src/test/parse-fail/range_inclusive_gate.rs
index 021b6dd3e26..30dc6fc5b20 100644
--- a/src/test/parse-fail/range_inclusive_gate.rs
+++ b/src/test/parse-fail/range_inclusive_gate.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// gate-test-inclusive_range_syntax
+
 // Make sure that #![feature(inclusive_range_syntax)] is required.
 
 // #![feature(inclusive_range_syntax, inclusive_range)]
diff --git a/src/test/run-make/graphviz-flowgraph/f10.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f10.dot-expected.dot
index a3b531b1e2f..07b9c744a71 100644
--- a/src/test/run-make/graphviz-flowgraph/f10.dot-expected.dot
+++ b/src/test/run-make/graphviz-flowgraph/f10.dot-expected.dot
@@ -5,10 +5,10 @@ digraph block {
     N3[label="local mut x"];
     N4[label="stmt let mut x = 10;"];
     N5[label="(dummy_node)"];
-    N6[label="expr x"];
-    N7[label="expr 0"];
-    N8[label="expr x > 0"];
-    N9[label="expr while x > 0 { x -= 1; }"];
+    N6[label="expr while x > 0 { x -= 1; }"];
+    N7[label="expr x"];
+    N8[label="expr 0"];
+    N9[label="expr x > 0"];
     N10[label="expr 1"];
     N11[label="expr x"];
     N12[label="expr x -= 1"];
@@ -20,17 +20,17 @@ digraph block {
     N2 -> N3;
     N3 -> N4;
     N4 -> N5;
-    N5 -> N6;
-    N6 -> N7;
+    N5 -> N7;
     N7 -> N8;
     N8 -> N9;
-    N8 -> N10;
+    N9 -> N6;
+    N9 -> N10;
     N10 -> N11;
     N11 -> N12;
     N12 -> N13;
     N13 -> N14;
     N14 -> N5;
-    N9 -> N15;
+    N6 -> N15;
     N15 -> N16;
     N16 -> N1;
 }
diff --git a/src/test/run-make/graphviz-flowgraph/f23.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f23.dot-expected.dot
index f152977438c..c8bfcd6510b 100644
--- a/src/test/run-make/graphviz-flowgraph/f23.dot-expected.dot
+++ b/src/test/run-make/graphviz-flowgraph/f23.dot-expected.dot
@@ -11,28 +11,28 @@ digraph block {
     N9[label="local mut z"];
     N10[label="stmt let mut z = 23;"];
     N11[label="(dummy_node)"];
-    N12[label="expr x"];
-    N13[label="expr 0"];
-    N14[label="expr x > 0"];
-    N15[label="expr while x > 0 {\l    x -= 1;\l    while y > 0 {\l        y -= 1;\l        while z > 0 { z -= 1; }\l        if x > 10 { return; \"unreachable\"; }\l    }\l}\l"];
+    N12[label="expr while x > 0 {\l    x -= 1;\l    while y > 0 {\l        y -= 1;\l        while z > 0 { z -= 1; }\l        if x > 10 { return; \"unreachable\"; }\l    }\l}\l"];
+    N13[label="expr x"];
+    N14[label="expr 0"];
+    N15[label="expr x > 0"];
     N16[label="expr 1"];
     N17[label="expr x"];
     N18[label="expr x -= 1"];
     N19[label="stmt x -= 1;"];
     N20[label="(dummy_node)"];
-    N21[label="expr y"];
-    N22[label="expr 0"];
-    N23[label="expr y > 0"];
-    N24[label="expr while y > 0 {\l    y -= 1;\l    while z > 0 { z -= 1; }\l    if x > 10 { return; \"unreachable\"; }\l}\l"];
+    N21[label="expr while y > 0 {\l    y -= 1;\l    while z > 0 { z -= 1; }\l    if x > 10 { return; \"unreachable\"; }\l}\l"];
+    N22[label="expr y"];
+    N23[label="expr 0"];
+    N24[label="expr y > 0"];
     N25[label="expr 1"];
     N26[label="expr y"];
     N27[label="expr y -= 1"];
     N28[label="stmt y -= 1;"];
     N29[label="(dummy_node)"];
-    N30[label="expr z"];
-    N31[label="expr 0"];
-    N32[label="expr z > 0"];
-    N33[label="expr while z > 0 { z -= 1; }"];
+    N30[label="expr while z > 0 { z -= 1; }"];
+    N31[label="expr z"];
+    N32[label="expr 0"];
+    N33[label="expr z > 0"];
     N34[label="expr 1"];
     N35[label="expr z"];
     N36[label="expr z -= 1"];
@@ -63,35 +63,35 @@ digraph block {
     N8 -> N9;
     N9 -> N10;
     N10 -> N11;
-    N11 -> N12;
-    N12 -> N13;
+    N11 -> N13;
     N13 -> N14;
     N14 -> N15;
-    N14 -> N16;
+    N15 -> N12;
+    N15 -> N16;
     N16 -> N17;
     N17 -> N18;
     N18 -> N19;
     N19 -> N20;
-    N20 -> N21;
-    N21 -> N22;
+    N20 -> N22;
     N22 -> N23;
     N23 -> N24;
-    N23 -> N25;
+    N24 -> N21;
+    N24 -> N25;
     N25 -> N26;
     N26 -> N27;
     N27 -> N28;
     N28 -> N29;
-    N29 -> N30;
-    N30 -> N31;
+    N29 -> N31;
     N31 -> N32;
     N32 -> N33;
-    N32 -> N34;
+    N33 -> N30;
+    N33 -> N34;
     N34 -> N35;
     N35 -> N36;
     N36 -> N37;
     N37 -> N38;
     N38 -> N29;
-    N33 -> N39;
+    N30 -> N39;
     N39 -> N40;
     N40 -> N41;
     N41 -> N42;
@@ -105,9 +105,9 @@ digraph block {
     N48 -> N49;
     N49 -> N50;
     N50 -> N20;
-    N24 -> N51;
+    N21 -> N51;
     N51 -> N11;
-    N15 -> N52;
+    N12 -> N52;
     N52 -> N53;
     N53 -> N1;
 }
diff --git a/src/test/compile-fail/static-recursion-gate.rs b/src/test/run-pass/auxiliary/clibrary.rs
index 29b5689fa93..7438ba21bfc 100644
--- a/src/test/compile-fail/static-recursion-gate.rs
+++ b/src/test/run-pass/auxiliary/clibrary.rs
@@ -1,4 +1,4 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// 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.
 //
@@ -8,9 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-static mut S: *const u8 = unsafe { &S as *const *const u8 as *const u8 };
-//~^ ERROR recursive static
+// no-prefer-dynamic
+#![crate_type = "staticlib"]
 
-pub fn main() {
-    unsafe { assert_eq!(S, *(S as *const *const u8)); }
-}
+#[no_mangle]
+pub extern "C" fn foo(x:i32) -> i32 { x }
diff --git a/src/test/run-pass/auxiliary/issue_39823.rs b/src/test/run-pass/auxiliary/issue_39823.rs
new file mode 100644
index 00000000000..5342601ac14
--- /dev/null
+++ b/src/test/run-pass/auxiliary/issue_39823.rs
@@ -0,0 +1,17 @@
+// Copyright 2017 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.
+
+#![crate_type="rlib"]
+
+#[derive(Debug, PartialEq)]
+pub struct RemoteC(pub u32);
+
+#[derive(Debug, PartialEq)]
+pub struct RemoteG<T>(pub T);
diff --git a/src/test/run-pass/closure-to-fn-coercion.rs b/src/test/run-pass/closure-to-fn-coercion.rs
new file mode 100644
index 00000000000..13d1d6aa139
--- /dev/null
+++ b/src/test/run-pass/closure-to-fn-coercion.rs
@@ -0,0 +1,41 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-stage0: new feature, remove this when SNAP
+
+#![feature(closure_to_fn_coercion)]
+
+const FOO: fn(u8) -> u8 = |v: u8| { v };
+
+const BAR: [fn(&mut u32); 5] = [
+    |_: &mut u32| {},
+    |v: &mut u32| *v += 1,
+    |v: &mut u32| *v += 2,
+    |v: &mut u32| *v += 3,
+    |v: &mut u32| *v += 4,
+];
+fn func_specific() -> (fn() -> u32) {
+    || return 42
+}
+
+fn main() {
+    // Items
+    assert_eq!(func_specific()(), 42);
+    let foo: fn(u8) -> u8 = |v: u8| { v };
+    assert_eq!(foo(31), 31);
+    // Constants
+    assert_eq!(FOO(31), 31);
+    let mut a: u32 = 0;
+    assert_eq!({ BAR[0](&mut a); a }, 0);
+    assert_eq!({ BAR[1](&mut a); a }, 1);
+    assert_eq!({ BAR[2](&mut a); a }, 3);
+    assert_eq!({ BAR[3](&mut a); a }, 6);
+    assert_eq!({ BAR[4](&mut a); a }, 10);
+}
diff --git a/src/test/run-pass/issue-2063-resource.rs b/src/test/run-pass/issue-2063-resource.rs
index aa9a7afc37f..c3a0dc67e83 100644
--- a/src/test/run-pass/issue-2063-resource.rs
+++ b/src/test/run-pass/issue-2063-resource.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(static_recursion)]
-
 // test that autoderef of a type like this does not
 // cause compiler to loop.  Note that no instances
 // of such a type could ever be constructed.
diff --git a/src/test/run-pass/issue-2063.rs b/src/test/run-pass/issue-2063.rs
index 48da7ecc508..5be4f8e8e73 100644
--- a/src/test/run-pass/issue-2063.rs
+++ b/src/test/run-pass/issue-2063.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(static_recursion)]
-
 // test that autoderef of a type like this does not
 // cause compiler to loop.  Note that no instances
 // of such a type could ever be constructed.
diff --git a/src/test/run-pass/issue-38972.rs b/src/test/run-pass/issue-38972.rs
new file mode 100644
index 00000000000..d5df84e0fb0
--- /dev/null
+++ b/src/test/run-pass/issue-38972.rs
@@ -0,0 +1,25 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This issue tracks a regression (a new warning) without
+// feature(never_type). When we make that the default, please
+// remove this test.
+
+enum Foo { }
+
+fn make_foo() -> Option<Foo> { None }
+
+#[deny(warnings)]
+fn main() {
+    match make_foo() {
+        None => {},
+        Some(_) => {}
+    }
+}
diff --git a/src/test/run-pass/issue-39823.rs b/src/test/run-pass/issue-39823.rs
new file mode 100644
index 00000000000..061a55b03b2
--- /dev/null
+++ b/src/test/run-pass/issue-39823.rs
@@ -0,0 +1,34 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:issue_39823.rs
+
+extern crate issue_39823;
+use issue_39823::{RemoteC, RemoteG};
+
+#[derive(Debug, PartialEq)]
+struct LocalC(u32);
+
+#[derive(Debug, PartialEq)]
+struct LocalG<T>(T);
+
+fn main() {
+    let virtual_localc : &Fn(_) -> LocalC = &LocalC;
+    assert_eq!(virtual_localc(1), LocalC(1));
+
+    let virtual_localg : &Fn(_) -> LocalG<u32> = &LocalG;
+    assert_eq!(virtual_localg(1), LocalG(1));
+
+    let virtual_remotec : &Fn(_) -> RemoteC = &RemoteC;
+    assert_eq!(virtual_remotec(1), RemoteC(1));
+
+    let virtual_remoteg : &Fn(_) -> RemoteG<u32> = &RemoteG;
+    assert_eq!(virtual_remoteg(1), RemoteG(1));
+}
diff --git a/src/test/run-pass/iter-sum-overflow-overflow-checks.rs b/src/test/run-pass/iter-sum-overflow-overflow-checks.rs
new file mode 100644
index 00000000000..a3a7179fb71
--- /dev/null
+++ b/src/test/run-pass/iter-sum-overflow-overflow-checks.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.
+
+// compile-flags: -C overflow-checks
+
+use std::panic;
+
+fn main() {
+    let r = panic::catch_unwind(|| {
+        [1, i32::max_value()].iter().sum::<i32>();
+    });
+    assert!(r.is_err());
+
+    let r = panic::catch_unwind(|| {
+        [2, i32::max_value()].iter().product::<i32>();
+    });
+    assert!(r.is_err());
+
+    let r = panic::catch_unwind(|| {
+        [1, i32::max_value()].iter().cloned().sum::<i32>();
+    });
+    assert!(r.is_err());
+
+    let r = panic::catch_unwind(|| {
+        [2, i32::max_value()].iter().cloned().product::<i32>();
+    });
+    assert!(r.is_err());
+}
diff --git a/src/test/run-pass/lib-defaults.rs b/src/test/run-pass/lib-defaults.rs
new file mode 100644
index 00000000000..a38080f8cfe
--- /dev/null
+++ b/src/test/run-pass/lib-defaults.rs
@@ -0,0 +1,23 @@
+// Copyright 2017 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.
+
+// aux-build:clibrary.rs
+// compile-flags: -lclibrary
+
+#[link(name = "clibrary", kind = "static")]
+extern "C" {
+    pub fn foo(x:i32) -> i32;
+}
+
+fn main() {
+    unsafe {
+        foo(42);
+    }
+}
diff --git a/src/test/run-pass/loop-break-value.rs b/src/test/run-pass/loop-break-value.rs
index 6a5e051c0c7..4906a8e71d7 100644
--- a/src/test/run-pass/loop-break-value.rs
+++ b/src/test/run-pass/loop-break-value.rs
@@ -124,10 +124,18 @@ pub fn main() {
     assert_eq!(nested_break_value, "hello");
 
     let break_from_while_cond = loop {
-        while break {
+        'inner_loop: while break 'inner_loop {
             panic!();
         }
         break 123;
     };
     assert_eq!(break_from_while_cond, 123);
+
+    let break_from_while_to_outer = 'outer_loop: loop {
+        while break 'outer_loop 567 {
+            panic!("from_inner");
+        }
+        panic!("from outer");
+    };
+    assert_eq!(break_from_while_to_outer, 567);
 }
diff --git a/src/test/run-pass/panic-safe.rs b/src/test/run-pass/panic-safe.rs
index 493a00ac5d0..9bda07f077f 100644
--- a/src/test/run-pass/panic-safe.rs
+++ b/src/test/run-pass/panic-safe.rs
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 #![allow(dead_code)]
-#![feature(recover)]
 
 use std::panic::{UnwindSafe, AssertUnwindSafe};
 use std::cell::RefCell;
@@ -40,6 +39,10 @@ fn main() {
     assert::<&RwLock<i32>>();
     assert::<Rc<i32>>();
     assert::<Arc<i32>>();
+    assert::<Box<[u8]>>();
+
+    trait Trait: UnwindSafe {}
+    assert::<Box<Trait>>();
 
     fn bar<T>() {
         assert::<Mutex<T>>();
diff --git a/src/test/run-pass/static-recursive.rs b/src/test/run-pass/static-recursive.rs
index f3db102ea5a..4a6ba984eef 100644
--- a/src/test/run-pass/static-recursive.rs
+++ b/src/test/run-pass/static-recursive.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(static_recursion)]
-
 static mut S: *const u8 = unsafe { &S as *const *const u8 as *const u8 };
 
 struct StaticDoubleLinked {
diff --git a/src/test/ui/mismatched_types/E0053.stderr b/src/test/ui/mismatched_types/E0053.stderr
index b6e3d663e36..d9871b8970c 100644
--- a/src/test/ui/mismatched_types/E0053.stderr
+++ b/src/test/ui/mismatched_types/E0053.stderr
@@ -6,6 +6,9 @@ error[E0053]: method `foo` has an incompatible type for trait
 ...
 19 |     fn foo(x: i16) { }
    |               ^^^ expected u16, found i16
+   |
+   = note: expected type `fn(u16)`
+              found type `fn(i16)`
 
 error[E0053]: method `bar` has an incompatible type for trait
   --> $DIR/E0053.rs:22:12
diff --git a/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr b/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr
index 991197c2afb..349432f64bb 100644
--- a/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr
+++ b/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr
@@ -6,6 +6,9 @@ error[E0053]: method `foo` has an incompatible type for trait
 ...
 21 |     fn foo(x: i16) { }
    |               ^^^ expected u16, found i16
+   |
+   = note: expected type `fn(u16)`
+              found type `fn(i16)`
 
 error[E0053]: method `bar` has an incompatible type for trait
   --> $DIR/trait-impl-fn-incompatibility.rs:22:28
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index 991cd02d215..6d40dcacdba 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -215,6 +215,10 @@ impl Builder {
         self.package("rust-docs", &mut manifest.pkg, TARGETS);
         self.package("rust-src", &mut manifest.pkg, &["*"]);
 
+        if self.channel == "rust-nightly" {
+            self.package("analysis", &mut manifest.pkg, TARGETS);
+        }
+
         let mut pkg = Package {
             version: self.cached_version("rust").to_string(),
             target: HashMap::new(),
@@ -264,6 +268,12 @@ impl Builder {
                         target: target.to_string(),
                     });
                 }
+                if self.channel == "nightly" {
+                    extensions.push(Component {
+                        pkg: "rust-analysis".to_string(),
+                        target: target.to_string(),
+                    });
+                }
             }
             extensions.push(Component {
                 pkg: "rust-src".to_string(),
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index c9bdcd408ea..1ec0838d45f 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1987,12 +1987,22 @@ actual:\n\
     fn check_rustdoc_test_option(&self, res: ProcRes) {
         let mut other_files = Vec::new();
         let mut files: HashMap<String, Vec<usize>> = HashMap::new();
-        files.insert(self.testpaths.file.to_str().unwrap().to_owned(),
+        let cwd = env::current_dir().unwrap();
+        files.insert(self.testpaths.file.strip_prefix(&cwd)
+                                        .unwrap_or(&self.testpaths.file)
+                                        .to_str()
+                                        .unwrap()
+                                        .replace('\\', "/"),
                      self.get_lines(&self.testpaths.file, Some(&mut other_files)));
         for other_file in other_files {
             let mut path = self.testpaths.file.clone();
             path.set_file_name(&format!("{}.rs", other_file));
-            files.insert(path.to_str().unwrap().to_owned(), self.get_lines(&path, None));
+            files.insert(path.strip_prefix(&cwd)
+                             .unwrap_or(&path)
+                             .to_str()
+                             .unwrap()
+                             .replace('\\', "/"),
+                         self.get_lines(&path, None));
         }
 
         let mut tested = 0;
@@ -2002,7 +2012,8 @@ actual:\n\
                                let tmp: Vec<&str> = s.split(" - ").collect();
                                if tmp.len() == 2 {
                                    let path = tmp[0].rsplit("test ").next().unwrap();
-                                   if let Some(ref mut v) = files.get_mut(path) {
+                                   if let Some(ref mut v) = files.get_mut(
+                                                                &path.replace('\\', "/")) {
                                        tested += 1;
                                        let mut iter = tmp[1].split("(line ");
                                        iter.next();
diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs
index 13f272517b1..2c81382bc9b 100644
--- a/src/tools/tidy/src/features.rs
+++ b/src/tools/tidy/src/features.rs
@@ -116,7 +116,8 @@ pub fn check(path: &Path, bad: &mut bool) {
     });
 
     super::walk_many(&[&path.join("test/compile-fail"),
-                       &path.join("test/compile-fail-fulldeps")],
+                       &path.join("test/compile-fail-fulldeps"),
+                       &path.join("test/parse-fail"),],
                      &mut |path| super::filter_dirs(path),
                      &mut |file| {
         let filename = file.file_name().unwrap().to_string_lossy();
@@ -169,8 +170,7 @@ pub fn check(path: &Path, bad: &mut bool) {
         "abi_ptx", "simd",
         "cfg_target_has_atomic",
         "unboxed_closures", "stmt_expr_attributes",
-        "cfg_target_thread_local", "unwind_attributes",
-        "inclusive_range_syntax"
+        "cfg_target_thread_local", "unwind_attributes"
     ];
 
     // Only check the number of lang features.