about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-09-13 22:40:35 +0000
committerbors <bors@rust-lang.org>2018-09-13 22:40:35 +0000
commit4f921d7a8d8dee7b511e4956e06a80f550003afc (patch)
tree2669f8223a1f824c967e590624e285a31c1f6e49
parent90d36fb5905bbe5004f5b465ea14b53d10dae260 (diff)
parent07dc4b3759f3cc0e97777fe944dbc54c967424fd (diff)
downloadrust-4f921d7a8d8dee7b511e4956e06a80f550003afc.tar.gz
rust-4f921d7a8d8dee7b511e4956e06a80f550003afc.zip
Auto merge of #54168 - kennytm:rollup, r=kennytm
Rollup of 11 pull requests

Successful merges:

 - #53371 (Do not emit E0277 on incorrect tuple destructured binding)
 - #53829 (Add rustc SHA to released DWARF debuginfo)
 - #53950 (Allow for opting out of ThinLTO and clean up LTO related cli flag handling.)
 - #53976 (Replace unwrap calls in example by expect)
 - #54070 (Add Error::description soft-deprecation to RELEASES)
 - #54076 (miri loop detector hashing)
 - #54119 (Add some unit tests for find_best_match_for_name)
 - #54147 (Add a test that tries to modify static memory at compile-time)
 - #54150 (Updated 1.29 release notes with --document-private-items flag)
 - #54163 (Update stage 0 to latest beta)
 - #54170 (COMPILER_TESTS.md has been moved)
-rw-r--r--CONTRIBUTING.md5
-rw-r--r--RELEASES.md6
-rw-r--r--config.toml.example4
-rw-r--r--src/bootstrap/bin/rustc.rs4
-rw-r--r--src/bootstrap/builder.rs8
-rw-r--r--src/bootstrap/cc_detect.rs4
-rw-r--r--src/bootstrap/compile.rs4
-rw-r--r--src/bootstrap/config.rs3
-rw-r--r--src/bootstrap/lib.rs32
-rw-r--r--src/bootstrap/native.rs7
-rw-r--r--src/bootstrap/test.rs4
-rwxr-xr-xsrc/ci/run.sh1
-rw-r--r--src/librustc/session/config.rs60
-rw-r--r--src/librustc/session/mod.rs25
-rw-r--r--src/librustc_codegen_llvm/back/link.rs1
-rw-r--r--src/librustc_codegen_llvm/back/linker.rs3
-rw-r--r--src/librustc_codegen_llvm/back/lto.rs3
-rw-r--r--src/librustc_codegen_llvm/back/write.rs5
-rw-r--r--src/librustc_mir/const_eval.rs1
-rw-r--r--src/librustc_mir/interpret/eval_context.rs8
-rw-r--r--src/librustc_mir/interpret/machine.rs14
-rw-r--r--src/librustc_mir/interpret/place.rs7
-rw-r--r--src/librustc_mir/interpret/snapshot.rs29
-rw-r--r--src/librustc_mir/interpret/step.rs5
-rw-r--r--src/librustc_typeck/check/_match.rs18
-rw-r--r--src/libstd/build.rs4
-rw-r--r--src/libstd/ffi/c_str.rs64
-rw-r--r--src/libsyntax/util/lev_distance.rs42
-rw-r--r--src/stage0.txt2
-rw-r--r--src/test/run-make-fulldeps/codegen-options-parsing/Makefile6
-rw-r--r--src/test/run-make-fulldeps/lto-smoke/Makefile26
-rw-r--r--src/test/ui/consts/const-eval/mod-static-with-const-fn.rs37
-rw-r--r--src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr18
-rw-r--r--src/test/ui/consts/const-size_of-cycle.rs2
-rw-r--r--src/test/ui/elide-errors-on-mismatched-tuple.rs28
-rw-r--r--src/test/ui/elide-errors-on-mismatched-tuple.stderr12
-rw-r--r--src/test/ui/impl-trait/impl-generic-mismatch.rs3
-rw-r--r--src/test/ui/impl-trait/impl-generic-mismatch.stderr6
38 files changed, 398 insertions, 113 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 21b14d011f9..2e51a786f46 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -368,8 +368,7 @@ will run all the tests on every platform we support. If it all works out,
 [merge-queue]: https://buildbot2.rust-lang.org/homu/queue/rust
 
 Speaking of tests, Rust has a comprehensive test suite. More information about
-it can be found
-[here](https://github.com/rust-lang/rust/blob/master/src/test/COMPILER_TESTS.md).
+it can be found [here][rctd].
 
 ### External Dependencies
 [external-dependencies]: #external-dependencies
@@ -654,5 +653,5 @@ are:
 [rustforge]: https://forge.rust-lang.org/
 [tlgba]: http://tomlee.co/2014/04/a-more-detailed-tour-of-the-rust-compiler/
 [ro]: http://www.rustaceans.org/
-[rctd]: ./src/test/COMPILER_TESTS.md
+[rctd]: https://rust-lang-nursery.github.io/rustc-guide/tests/intro.html
 [cheatsheet]: https://buildbot2.rust-lang.org/homu/
diff --git a/RELEASES.md b/RELEASES.md
index 7e727e0d41b..819c9184364 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -31,6 +31,8 @@ Cargo
   using `--target`][cargo/5614]
 - [Added the `cargo-fix` subcommand to automatically move project code from
   2015 edition to 2018.][cargo/5723]
+- [`cargo doc` can now optionally document private types using the
+  `--document-private-items` flag.][cargo/5543]
 
 Misc
 ----
@@ -68,6 +70,7 @@ Compatibility Notes
 [51178]: https://github.com/rust-lang/rust/pull/51178/
 [51122]: https://github.com/rust-lang/rust/pull/51122
 [50494]: https://github.com/rust-lang/rust/pull/50494/
+[cargo/5543]: https://github.com/rust-lang/cargo/pull/5543
 [cargo/5614]: https://github.com/rust-lang/cargo/pull/5614/
 [cargo/5723]: https://github.com/rust-lang/cargo/pull/5723/
 [cargo/5831]: https://github.com/rust-lang/cargo/pull/5831/
@@ -370,6 +373,8 @@ Compatibility Notes
 - [The maximum number for `repr(align(N))` is now 2²⁹.][50378] Previously you
   could enter higher numbers but they were not supported by LLVM. Up to 512MB
   alignment should cover all use cases.
+- The `.description()` method on the `std::error::Error` trait
+  [has been soft-deprecated][50163]. It is no longer required to implement it.
 
 [48553]: https://github.com/rust-lang/rust/pull/48553/
 [48851]: https://github.com/rust-lang/rust/pull/48851/
@@ -383,6 +388,7 @@ Compatibility Notes
 [49719]: https://github.com/rust-lang/rust/pull/49719/
 [49896]: https://github.com/rust-lang/rust/pull/49896/
 [49968]: https://github.com/rust-lang/rust/pull/49968/
+[50163]: https://github.com/rust-lang/rust/pull/50163
 [50177]: https://github.com/rust-lang/rust/pull/50177/
 [50378]: https://github.com/rust-lang/rust/pull/50378/
 [50398]: https://github.com/rust-lang/rust/pull/50398/
diff --git a/config.toml.example b/config.toml.example
index 087dc418e2d..3159c19528a 100644
--- a/config.toml.example
+++ b/config.toml.example
@@ -377,6 +377,10 @@
 # Whether to verify generated LLVM IR
 #verify-llvm-ir = false
 
+# Map all debuginfo paths for libstd and crates to `/rust/$sha/$crate/...`,
+# generally only set for releases
+#remap-debuginfo = false
+
 # =============================================================================
 # Options for specific targets
 #
diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs
index 7192cae8956..f30f34acf5c 100644
--- a/src/bootstrap/bin/rustc.rs
+++ b/src/bootstrap/bin/rustc.rs
@@ -263,6 +263,10 @@ fn main() {
         if env::var_os("RUSTC_FORCE_UNSTABLE").is_some() {
             cmd.arg("-Z").arg("force-unstable-if-unmarked");
         }
+
+        if let Ok(map) = env::var("RUSTC_DEBUGINFO_MAP") {
+            cmd.arg("--remap-path-prefix").arg(&map);
+        }
     } else {
         // Override linker if necessary.
         if let Ok(host_linker) = env::var("RUSTC_HOST_LINKER") {
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 5c287f25e26..2f7f3058b04 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -32,7 +32,7 @@ use native;
 use test;
 use tool;
 use util::{add_lib_path, exe, libdir};
-use {Build, DocTests, Mode};
+use {Build, DocTests, Mode, GitRepo};
 
 pub use Compiler;
 
@@ -876,6 +876,10 @@ impl<'a> Builder<'a> {
             cargo.env("RUSTC_HOST_CRT_STATIC", x.to_string());
         }
 
+        if let Some(map) = self.build.debuginfo_map(GitRepo::Rustc) {
+            cargo.env("RUSTC_DEBUGINFO_MAP", map);
+        }
+
         // Enable usage of unstable features
         cargo.env("RUSTC_BOOTSTRAP", "1");
         self.add_rust_test_threads(&mut cargo);
@@ -964,7 +968,7 @@ impl<'a> Builder<'a> {
             let cc = ccacheify(&self.cc(target));
             cargo.env(format!("CC_{}", target), &cc).env("CC", &cc);
 
-            let cflags = self.cflags(target).join(" ");
+            let cflags = self.cflags(target, GitRepo::Rustc).join(" ");
             cargo
                 .env(format!("CFLAGS_{}", target), cflags.clone())
                 .env("CFLAGS", cflags.clone());
diff --git a/src/bootstrap/cc_detect.rs b/src/bootstrap/cc_detect.rs
index 698903f128d..d5da0cabec8 100644
--- a/src/bootstrap/cc_detect.rs
+++ b/src/bootstrap/cc_detect.rs
@@ -39,7 +39,7 @@ use std::process::Command;
 use build_helper::output;
 use cc;
 
-use Build;
+use {Build, GitRepo};
 use config::Target;
 use cache::Interned;
 
@@ -107,7 +107,7 @@ pub fn find(build: &mut Build) {
 
         build.cc.insert(target, compiler);
         build.verbose(&format!("CC_{} = {:?}", &target, build.cc(target)));
-        build.verbose(&format!("CFLAGS_{} = {:?}", &target, build.cflags(target)));
+        build.verbose(&format!("CFLAGS_{} = {:?}", &target, build.cflags(target, GitRepo::Rustc)));
         if let Some(ar) = ar {
             build.verbose(&format!("AR_{} = {:?}", &target, ar));
             build.ar.insert(target, ar);
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index da0ccf5e177..c0661a773e3 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -30,7 +30,7 @@ use filetime::FileTime;
 use serde_json;
 
 use util::{exe, libdir, is_dylib, CiEnv};
-use {Compiler, Mode};
+use {Compiler, Mode, GitRepo};
 use native;
 use tool;
 
@@ -895,7 +895,7 @@ pub fn compiler_file(builder: &Builder,
                  target: Interned<String>,
                  file: &str) -> PathBuf {
     let mut cmd = Command::new(compiler);
-    cmd.args(builder.cflags(target));
+    cmd.args(builder.cflags(target, GitRepo::Rustc));
     cmd.arg(format!("-print-file-name={}", file));
     let out = output(&mut cmd);
     PathBuf::from(out.trim())
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 70b21a1567b..cc6d76c76f2 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -109,6 +109,7 @@ pub struct Config {
     pub rust_codegen_backends: Vec<Interned<String>>,
     pub rust_codegen_backends_dir: String,
     pub rust_verify_llvm_ir: bool,
+    pub rust_remap_debuginfo: bool,
 
     pub build: Interned<String>,
     pub hosts: Vec<Interned<String>>,
@@ -321,6 +322,7 @@ struct Rust {
     deny_warnings: Option<bool>,
     backtrace_on_ice: Option<bool>,
     verify_llvm_ir: Option<bool>,
+    remap_debuginfo: Option<bool>,
 }
 
 /// TOML representation of how each build target is configured.
@@ -557,6 +559,7 @@ impl Config {
             set(&mut config.deny_warnings, rust.deny_warnings.or(flags.warnings));
             set(&mut config.backtrace_on_ice, rust.backtrace_on_ice);
             set(&mut config.rust_verify_llvm_ir, rust.verify_llvm_ir);
+            set(&mut config.rust_remap_debuginfo, rust.remap_debuginfo);
 
             if let Some(ref backends) = rust.codegen_backends {
                 config.rust_codegen_backends = backends.iter()
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 2725abdc3d9..ed6a5f94d0d 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -237,6 +237,11 @@ pub enum DocTests {
     Only,
 }
 
+pub enum GitRepo {
+    Rustc,
+    Llvm,
+}
+
 /// Global configuration for the build system.
 ///
 /// This structure transitively contains all configuration for the build system.
@@ -738,6 +743,21 @@ impl Build {
         self.config.jobs.unwrap_or_else(|| num_cpus::get() as u32)
     }
 
+    fn debuginfo_map(&self, which: GitRepo) -> Option<String> {
+        if !self.config.rust_remap_debuginfo {
+            return None
+        }
+
+        let path = match which {
+            GitRepo::Rustc => {
+                let sha = self.rust_info.sha().expect("failed to find sha");
+                format!("/rustc/{}", sha)
+            }
+            GitRepo::Llvm => format!("/rustc/llvm"),
+        };
+        Some(format!("{}={}", self.src.display(), path))
+    }
+
     /// Returns the path to the C compiler for the target specified.
     fn cc(&self, target: Interned<String>) -> &Path {
         self.cc[&target].path()
@@ -745,7 +765,7 @@ impl Build {
 
     /// Returns a list of flags to pass to the C compiler for the target
     /// specified.
-    fn cflags(&self, target: Interned<String>) -> Vec<String> {
+    fn cflags(&self, target: Interned<String>, which: GitRepo) -> Vec<String> {
         // Filter out -O and /O (the optimization flags) that we picked up from
         // cc-rs because the build scripts will determine that for themselves.
         let mut base = self.cc[&target].args().iter()
@@ -767,6 +787,16 @@ impl Build {
         if &*target == "i686-pc-windows-gnu" {
             base.push("-fno-omit-frame-pointer".into());
         }
+
+        if let Some(map) = self.debuginfo_map(which) {
+        let cc = self.cc(target);
+            if cc.ends_with("clang") || cc.ends_with("gcc") {
+                base.push(format!("-fdebug-prefix-map={}", map).into());
+            } else if cc.ends_with("clang-cl.exe") {
+                base.push("-Xclang".into());
+                base.push(format!("-fdebug-prefix-map={}", map).into());
+            }
+        }
         base
     }
 
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index 828a7d14c04..424264647f0 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -33,6 +33,7 @@ use util::{self, exe};
 use build_helper::up_to_date;
 use builder::{Builder, RunConfig, ShouldRun, Step};
 use cache::Interned;
+use GitRepo;
 
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
 pub struct Llvm {
@@ -373,8 +374,8 @@ fn configure_cmake(builder: &Builder,
     }
 
     cfg.build_arg("-j").build_arg(builder.jobs().to_string());
-    cfg.define("CMAKE_C_FLAGS", builder.cflags(target).join(" "));
-    let mut cxxflags = builder.cflags(target).join(" ");
+    cfg.define("CMAKE_C_FLAGS", builder.cflags(target, GitRepo::Llvm).join(" "));
+    let mut cxxflags = builder.cflags(target, GitRepo::Llvm).join(" ");
     if building_dist_binaries {
         if builder.config.llvm_static_stdcpp && !target.contains("windows") {
             cxxflags.push_str(" -static-libstdc++");
@@ -680,7 +681,7 @@ impl Step for Openssl {
         };
         configure.arg(os);
         configure.env("CC", builder.cc(target));
-        for flag in builder.cflags(target) {
+        for flag in builder.cflags(target, GitRepo::Rustc) {
             configure.arg(flag);
         }
         // There is no specific os target for android aarch64 or x86_64,
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 8e42c9c1ec7..92665c09f72 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -34,7 +34,7 @@ use tool::{self, Tool, SourceType};
 use toolstate::ToolState;
 use util::{self, dylib_path, dylib_path_var};
 use Crate as CargoCrate;
-use {DocTests, Mode};
+use {DocTests, Mode, GitRepo};
 
 const ADB_TEST_DIR: &str = "/data/tmp/work";
 
@@ -1142,7 +1142,7 @@ impl Step for Compiletest {
                     .arg("--cxx")
                     .arg(builder.cxx(target).unwrap())
                     .arg("--cflags")
-                    .arg(builder.cflags(target).join(" "))
+                    .arg(builder.cflags(target, GitRepo::Rustc).join(" "))
                     .arg("--llvm-components")
                     .arg(llvm_components.trim())
                     .arg("--llvm-cxxflags")
diff --git a/src/ci/run.sh b/src/ci/run.sh
index 09a0cf3541d..6a571bfad13 100755
--- a/src/ci/run.sh
+++ b/src/ci/run.sh
@@ -55,6 +55,7 @@ export RUST_RELEASE_CHANNEL=nightly
 if [ "$DEPLOY$DEPLOY_ALT" != "" ]; then
   RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --release-channel=$RUST_RELEASE_CHANNEL"
   RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-static-stdcpp"
+  RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.remap-debuginfo"
 
   if [ "$NO_LLVM_ASSERTIONS" = "1" ]; then
     RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-llvm-assertions"
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 73c9729feee..2a9732bf02c 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -68,15 +68,13 @@ pub enum OptLevel {
     SizeMin,    // -Oz
 }
 
+/// This is what the `LtoCli` values get mapped to after resolving defaults and
+/// and taking other command line options into account.
 #[derive(Clone, Copy, PartialEq, Hash, Debug)]
 pub enum Lto {
     /// Don't do any LTO whatsoever
     No,
 
-    /// Do a full crate graph LTO. The flavor is determined by the compiler
-    /// (currently the default is "fat").
-    Yes,
-
     /// Do a full crate graph LTO with ThinLTO
     Thin,
 
@@ -88,6 +86,23 @@ pub enum Lto {
     Fat,
 }
 
+/// The different settings that the `-C lto` flag can have.
+#[derive(Clone, Copy, PartialEq, Hash, Debug)]
+pub enum LtoCli {
+    /// `-C lto=no`
+    No,
+    /// `-C lto=yes`
+    Yes,
+    /// `-C lto`
+    NoParam,
+    /// `-C lto=thin`
+    Thin,
+    /// `-C lto=fat`
+    Fat,
+    /// No `-C lto` flag passed
+    Unspecified,
+}
+
 #[derive(Clone, PartialEq, Hash)]
 pub enum CrossLangLto {
     LinkerPlugin(PathBuf),
@@ -801,7 +816,8 @@ macro_rules! options {
         pub const parse_unpretty: Option<&'static str> =
             Some("`string` or `string=string`");
         pub const parse_lto: Option<&'static str> =
-            Some("one of `thin`, `fat`, or omitted");
+            Some("either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, \
+                  `fat`, or omitted");
         pub const parse_cross_lang_lto: Option<&'static str> =
             Some("either a boolean (`yes`, `no`, `on`, `off`, etc), \
                   or the path to the linker plugin");
@@ -809,7 +825,7 @@ macro_rules! options {
 
     #[allow(dead_code)]
     mod $mod_set {
-        use super::{$struct_name, Passes, Sanitizer, Lto, CrossLangLto};
+        use super::{$struct_name, Passes, Sanitizer, LtoCli, CrossLangLto};
         use rustc_target::spec::{LinkerFlavor, PanicStrategy, RelroLevel};
         use std::path::PathBuf;
 
@@ -1002,11 +1018,23 @@ macro_rules! options {
             }
         }
 
-        fn parse_lto(slot: &mut Lto, v: Option<&str>) -> bool {
+        fn parse_lto(slot: &mut LtoCli, v: Option<&str>) -> bool {
+            if v.is_some() {
+                let mut bool_arg = None;
+                if parse_opt_bool(&mut bool_arg, v) {
+                    *slot = if bool_arg.unwrap() {
+                        LtoCli::Yes
+                    } else {
+                        LtoCli::No
+                    };
+                    return true
+                }
+            }
+
             *slot = match v {
-                None => Lto::Yes,
-                Some("thin") => Lto::Thin,
-                Some("fat") => Lto::Fat,
+                None => LtoCli::NoParam,
+                Some("thin") => LtoCli::Thin,
+                Some("fat") => LtoCli::Fat,
                 Some(_) => return false,
             };
             true
@@ -1047,7 +1075,7 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options,
         "extra arguments to append to the linker invocation (space separated)"),
     link_dead_code: bool = (false, parse_bool, [UNTRACKED],
         "don't let linker strip dead code (turning it on can be used for code coverage)"),
-    lto: Lto = (Lto::No, parse_lto, [TRACKED],
+    lto: LtoCli = (LtoCli::Unspecified, parse_lto, [TRACKED],
         "perform LLVM link-time optimizations"),
     target_cpu: Option<String> = (None, parse_opt_string, [TRACKED],
         "select target processor (rustc --print target-cpus for details)"),
@@ -2384,8 +2412,8 @@ mod dep_tracking {
     use std::hash::Hash;
     use std::path::PathBuf;
     use std::collections::hash_map::DefaultHasher;
-    use super::{CrateType, DebugInfo, ErrorOutputType, Lto, OptLevel, OutputTypes,
-                Passes, Sanitizer, CrossLangLto};
+    use super::{CrateType, DebugInfo, ErrorOutputType, OptLevel, OutputTypes,
+                Passes, Sanitizer, LtoCli, CrossLangLto};
     use syntax::feature_gate::UnstableFeatures;
     use rustc_target::spec::{PanicStrategy, RelroLevel, TargetTriple};
     use syntax::edition::Edition;
@@ -2440,7 +2468,7 @@ mod dep_tracking {
     impl_dep_tracking_hash_via_hash!(RelroLevel);
     impl_dep_tracking_hash_via_hash!(Passes);
     impl_dep_tracking_hash_via_hash!(OptLevel);
-    impl_dep_tracking_hash_via_hash!(Lto);
+    impl_dep_tracking_hash_via_hash!(LtoCli);
     impl_dep_tracking_hash_via_hash!(DebugInfo);
     impl_dep_tracking_hash_via_hash!(UnstableFeatures);
     impl_dep_tracking_hash_via_hash!(OutputTypes);
@@ -2514,7 +2542,7 @@ mod tests {
     use lint;
     use middle::cstore;
     use session::config::{build_configuration, build_session_options_and_crate_config};
-    use session::config::{Lto, CrossLangLto};
+    use session::config::{LtoCli, CrossLangLto};
     use session::build_session;
     use std::collections::{BTreeMap, BTreeSet};
     use std::iter::FromIterator;
@@ -2948,7 +2976,7 @@ mod tests {
 
         // Make sure changing a [TRACKED] option changes the hash
         opts = reference.clone();
-        opts.cg.lto = Lto::Fat;
+        opts.cg.lto = LtoCli::Fat;
         assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
 
         opts = reference.clone();
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index 272967282e0..619262abb0b 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -550,9 +550,27 @@ impl Session {
         // lto` and we've for whatever reason forced off ThinLTO via the CLI,
         // then ensure we can't use a ThinLTO.
         match self.opts.cg.lto {
-            config::Lto::No => {}
-            config::Lto::Yes if self.opts.cli_forced_thinlto_off => return config::Lto::Fat,
-            other => return other,
+            config::LtoCli::Unspecified => {
+                // The compiler was invoked without the `-Clto` flag. Fall
+                // through to the default handling
+            }
+            config::LtoCli::No => {
+                // The user explicitly opted out of any kind of LTO
+                return config::Lto::No;
+            }
+            config::LtoCli::Yes |
+            config::LtoCli::Fat |
+            config::LtoCli::NoParam => {
+                // All of these mean fat LTO
+                return config::Lto::Fat;
+            }
+            config::LtoCli::Thin => {
+                return if self.opts.cli_forced_thinlto_off {
+                    config::Lto::Fat
+                } else {
+                    config::Lto::Thin
+                };
+            }
         }
 
         // Ok at this point the target doesn't require anything and the user
@@ -1178,7 +1196,6 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
 
     if sess.opts.incremental.is_some() {
         match sess.lto() {
-            Lto::Yes |
             Lto::Thin |
             Lto::Fat => {
                 sess.err("can't perform LTO when compiling incrementally");
diff --git a/src/librustc_codegen_llvm/back/link.rs b/src/librustc_codegen_llvm/back/link.rs
index d50a56ad84a..8248385c127 100644
--- a/src/librustc_codegen_llvm/back/link.rs
+++ b/src/librustc_codegen_llvm/back/link.rs
@@ -1666,7 +1666,6 @@ fn relevant_lib(sess: &Session, lib: &NativeLibrary) -> bool {
 
 fn are_upstream_rust_objects_already_included(sess: &Session) -> bool {
     match sess.lto() {
-        Lto::Yes |
         Lto::Fat => true,
         Lto::Thin => {
             // If we defer LTO to the linker, we haven't run LTO ourselves, so
diff --git a/src/librustc_codegen_llvm/back/linker.rs b/src/librustc_codegen_llvm/back/linker.rs
index ebb229b7b6b..95be2d82123 100644
--- a/src/librustc_codegen_llvm/back/linker.rs
+++ b/src/librustc_codegen_llvm/back/linker.rs
@@ -205,13 +205,12 @@ impl<'a> GccLinker<'a> {
         self.linker_arg(&format!("-plugin-opt={}", opt_level));
         self.linker_arg(&format!("-plugin-opt=mcpu={}", llvm_util::target_cpu(self.sess)));
 
-        match self.sess.opts.cg.lto {
+        match self.sess.lto() {
             config::Lto::Thin |
             config::Lto::ThinLocal => {
                 self.linker_arg("-plugin-opt=thin");
             }
             config::Lto::Fat |
-            config::Lto::Yes |
             config::Lto::No => {
                 // default to regular LTO
             }
diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs
index 25bc662c408..364b469738f 100644
--- a/src/librustc_codegen_llvm/back/lto.rs
+++ b/src/librustc_codegen_llvm/back/lto.rs
@@ -118,7 +118,7 @@ pub(crate) fn run(cgcx: &CodegenContext,
         Lto::ThinLocal => SymbolExportLevel::Rust,
 
         // We're doing LTO for the entire crate graph
-        Lto::Yes | Lto::Fat | Lto::Thin => {
+        Lto::Fat | Lto::Thin => {
             symbol_export::crates_export_threshold(&cgcx.crate_types)
         }
 
@@ -201,7 +201,6 @@ pub(crate) fn run(cgcx: &CodegenContext,
                                              .map(|c| c.as_ptr())
                                              .collect::<Vec<_>>();
     match cgcx.lto {
-        Lto::Yes | // `-C lto` == fat LTO by default
         Lto::Fat => {
             assert!(cached_modules.is_empty());
             let opt_jobs = fat_lto(cgcx,
diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs
index 6b257ed4c3e..7b78d4fb4ff 100644
--- a/src/librustc_codegen_llvm/back/write.rs
+++ b/src/librustc_codegen_llvm/back/write.rs
@@ -937,7 +937,6 @@ fn need_pre_thin_lto_bitcode_for_incr_comp(sess: &Session) -> bool {
     }
 
     match sess.lto() {
-        Lto::Yes |
         Lto::Fat |
         Lto::No => false,
         Lto::Thin |
@@ -1372,7 +1371,7 @@ fn execute_optimize_work_item(cgcx: &CodegenContext,
         // require LTO so the request for LTO is always unconditionally
         // passed down to the backend, but we don't actually want to do
         // anything about it yet until we've got a final product.
-        Lto::Yes | Lto::Fat | Lto::Thin => {
+        Lto::Fat | Lto::Thin => {
             cgcx.crate_types.len() != 1 ||
                 cgcx.crate_types[0] != config::CrateType::Rlib
         }
@@ -1552,7 +1551,7 @@ fn start_executing_work(tcx: TyCtxt,
                 exported_symbols.insert(LOCAL_CRATE, copy_symbols(LOCAL_CRATE));
                 Some(Arc::new(exported_symbols))
             }
-            Lto::Yes | Lto::Fat | Lto::Thin => {
+            Lto::Fat | Lto::Thin => {
                 exported_symbols.insert(LOCAL_CRATE, copy_symbols(LOCAL_CRATE));
                 for &cnum in tcx.crates().iter() {
                     exported_symbols.insert(cnum, copy_symbols(cnum));
diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs
index 154830c2e77..82cc1b7f661 100644
--- a/src/librustc_mir/const_eval.rs
+++ b/src/librustc_mir/const_eval.rs
@@ -239,6 +239,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeEvaluator {
     type MemoryKinds = !;
 
     const MUT_STATIC_KIND: Option<!> = None; // no mutating of statics allowed
+    const DETECT_LOOPS: bool = true;
 
     fn find_fn<'a>(
         ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index f7277f8d276..740d4e038df 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -65,6 +65,8 @@ pub struct EvalContext<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
     /// detector period.
     pub(super) steps_since_detector_enabled: isize,
 
+    /// Extra state to detect loops.
+    /// FIXME: Move this to the CTFE machine's state, out of the general miri engine.
     pub(super) loop_detector: InfiniteLoopDetector<'a, 'mir, 'tcx, M>,
 }
 
@@ -110,6 +112,7 @@ pub struct Frame<'mir, 'tcx: 'mir> {
     pub stmt: usize,
 }
 
+// Not using the macro because that does not support types depending on 'tcx
 impl<'a, 'mir, 'tcx: 'mir> HashStable<StableHashingContext<'a>> for Frame<'mir, 'tcx> {
     fn hash_stable<W: StableHasherResult>(
         &self,
@@ -144,11 +147,14 @@ pub enum StackPopCleanup {
     None { cleanup: bool },
 }
 
+// Can't use the macro here because that does not support named enum fields.
 impl<'a> HashStable<StableHashingContext<'a>> for StackPopCleanup {
     fn hash_stable<W: StableHasherResult>(
         &self,
         hcx: &mut StableHashingContext<'a>,
-        hasher: &mut StableHasher<W>) {
+        hasher: &mut StableHasher<W>)
+    {
+        mem::discriminant(self).hash_stable(hcx, hasher);
         match self {
             StackPopCleanup::Goto(ref block) => block.hash_stable(hcx, hasher),
             StackPopCleanup::None { cleanup } => cleanup.hash_stable(hcx, hasher),
diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs
index 61963f6d3d3..f33cb479102 100644
--- a/src/librustc_mir/interpret/machine.rs
+++ b/src/librustc_mir/interpret/machine.rs
@@ -12,29 +12,29 @@
 //! This separation exists to ensure that no fancy miri features like
 //! interpreting common C functions leak into CTFE.
 
-use std::hash::Hash;
-
 use rustc::hir::def_id::DefId;
-use rustc::ich::StableHashingContext;
 use rustc::mir::interpret::{Allocation, EvalResult, Scalar};
 use rustc::mir;
 use rustc::ty::{self, layout::TyLayout, query::TyCtxtAt};
-use rustc_data_structures::stable_hasher::HashStable;
 
 use super::{EvalContext, PlaceTy, OpTy};
 
 /// Methods of this trait signifies a point where CTFE evaluation would fail
 /// and some use case dependent behaviour can instead be applied
-pub trait Machine<'mir, 'tcx>: Clone + Eq + Hash + for<'a> HashStable<StableHashingContext<'a>> {
+pub trait Machine<'mir, 'tcx>: Clone + Eq {
     /// Additional data that can be accessed via the Memory
-    type MemoryData: Clone + Eq + Hash + for<'a> HashStable<StableHashingContext<'a>>;
+    type MemoryData: Clone + Eq;
 
     /// Additional memory kinds a machine wishes to distinguish from the builtin ones
-    type MemoryKinds: ::std::fmt::Debug + Copy + Clone + Eq + Hash;
+    type MemoryKinds: ::std::fmt::Debug + Copy + Clone + Eq;
 
     /// The memory kind to use for mutated statics -- or None if those are not supported.
     const MUT_STATIC_KIND: Option<Self::MemoryKinds>;
 
+    /// Whether to attempt to detect infinite loops (any kind of infinite
+    /// execution, really).
+    const DETECT_LOOPS: bool;
+
     /// Entry point to all function calls.
     ///
     /// Returns either the mir to use for the call, or `None` if execution should
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index d01593ca5e9..64e0aeaaab7 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -13,6 +13,7 @@
 //! All high-level functions to write to memory work on places as destinations.
 
 use std::convert::TryFrom;
+use std::mem;
 
 use rustc::ich::StableHashingContext;
 use rustc::mir;
@@ -57,11 +58,13 @@ pub enum Place<Id=AllocId> {
     },
 }
 
+// Can't use the macro here because that does not support named enum fields.
 impl<'a> HashStable<StableHashingContext<'a>> for Place {
     fn hash_stable<W: StableHasherResult>(
         &self, hcx: &mut StableHashingContext<'a>,
-        hasher: &mut StableHasher<W>) {
-
+        hasher: &mut StableHasher<W>)
+    {
+        mem::discriminant(self).hash_stable(hcx, hasher);
         match self {
             Place::Ptr(mem_place) => mem_place.hash_stable(hcx, hasher),
 
diff --git a/src/librustc_mir/interpret/snapshot.rs b/src/librustc_mir/interpret/snapshot.rs
index 8aa053baae9..0e8466905eb 100644
--- a/src/librustc_mir/interpret/snapshot.rs
+++ b/src/librustc_mir/interpret/snapshot.rs
@@ -62,14 +62,13 @@ impl<'a, 'mir, 'tcx, M> InfiniteLoopDetector<'a, 'mir, 'tcx, M>
     pub fn observe_and_analyze(
         &mut self,
         tcx: &TyCtxt<'b, 'tcx, 'tcx>,
-        machine: &M,
         memory: &Memory<'a, 'mir, 'tcx, M>,
         stack: &[Frame<'mir, 'tcx>],
     ) -> EvalResult<'tcx, ()> {
 
         let mut hcx = tcx.get_stable_hashing_context();
         let mut hasher = StableHasher::<u64>::new();
-        (machine, stack).hash_stable(&mut hcx, &mut hasher);
+        stack.hash_stable(&mut hcx, &mut hasher);
         let hash = hasher.finish();
 
         if self.hashes.insert(hash) {
@@ -79,7 +78,7 @@ impl<'a, 'mir, 'tcx, M> InfiniteLoopDetector<'a, 'mir, 'tcx, M>
 
         info!("snapshotting the state of the interpreter");
 
-        if self.snapshots.insert(EvalSnapshot::new(machine, memory, stack)) {
+        if self.snapshots.insert(EvalSnapshot::new(memory, stack)) {
             // Spurious collision or first cycle
             return Ok(())
         }
@@ -345,7 +344,6 @@ impl<'a, 'b, 'mir, 'tcx, M> SnapshotContext<'b> for Memory<'a, 'mir, 'tcx, M>
 
 /// The virtual machine state during const-evaluation at a given point in time.
 struct EvalSnapshot<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
-    machine: M,
     memory: Memory<'a, 'mir, 'tcx, M>,
     stack: Vec<Frame<'mir, 'tcx>>,
 }
@@ -354,21 +352,20 @@ impl<'a, 'mir, 'tcx, M> EvalSnapshot<'a, 'mir, 'tcx, M>
     where M: Machine<'mir, 'tcx>,
 {
     fn new(
-        machine: &M,
         memory: &Memory<'a, 'mir, 'tcx, M>,
-        stack: &[Frame<'mir, 'tcx>]) -> Self {
-
+        stack: &[Frame<'mir, 'tcx>]
+    ) -> Self {
         EvalSnapshot {
-            machine: machine.clone(),
             memory: memory.clone(),
             stack: stack.into(),
         }
     }
 
     fn snapshot<'b: 'a>(&'b self)
-        -> (&'b M, MemorySnapshot<'b, 'mir, 'tcx, M>, Vec<FrameSnapshot<'a, 'tcx>>) {
-        let EvalSnapshot{ machine, memory, stack } = self;
-        (&machine, memory.snapshot(), stack.iter().map(|frame| frame.snapshot(memory)).collect())
+        -> (MemorySnapshot<'b, 'mir, 'tcx, M>, Vec<FrameSnapshot<'a, 'tcx>>)
+    {
+        let EvalSnapshot{ memory, stack } = self;
+        (memory.snapshot(), stack.iter().map(|frame| frame.snapshot(memory)).collect())
     }
 }
 
@@ -384,6 +381,8 @@ impl<'a, 'mir, 'tcx, M> Hash for EvalSnapshot<'a, 'mir, 'tcx, M>
     }
 }
 
+// Not using the macro because we need special handling for `memory`, which the macro
+// does not support at the same time as the extra bounds on the type.
 impl<'a, 'b, 'mir, 'tcx, M> HashStable<StableHashingContext<'b>>
     for EvalSnapshot<'a, 'mir, 'tcx, M>
     where M: Machine<'mir, 'tcx>,
@@ -391,10 +390,10 @@ impl<'a, 'b, 'mir, 'tcx, M> HashStable<StableHashingContext<'b>>
     fn hash_stable<W: StableHasherResult>(
         &self,
         hcx: &mut StableHashingContext<'b>,
-        hasher: &mut StableHasher<W>) {
-
-        let EvalSnapshot{ machine, memory, stack } = self;
-        (machine, &memory.data, stack).hash_stable(hcx, hasher);
+        hasher: &mut StableHasher<W>)
+    {
+        let EvalSnapshot{ memory: _, stack } = self;
+        stack.hash_stable(hcx, hasher);
     }
 }
 
diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs
index cb8e1284d09..5bdaf6ba729 100644
--- a/src/librustc_mir/interpret/step.rs
+++ b/src/librustc_mir/interpret/step.rs
@@ -65,6 +65,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
             }
         }
 
+        if !M::DETECT_LOOPS {
+            return Ok(());
+        }
+
         if self.loop_detector.is_empty() {
             // First run of the loop detector
 
@@ -75,7 +79,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
 
         self.loop_detector.observe_and_analyze(
             &self.tcx,
-            &self.machine,
             &self.memory,
             &self.stack[..],
         )
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 2a8ee4bd8df..7f65a5f0b5a 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -298,11 +298,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     TypeVariableOrigin::TypeInference(pat.span)));
                 let element_tys = tcx.mk_type_list(element_tys_iter);
                 let pat_ty = tcx.mk_ty(ty::Tuple(element_tys));
-                self.demand_eqtype(pat.span, expected, pat_ty);
-                for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
-                    self.check_pat_walk(elem, &element_tys[i], def_bm, true);
+                if let Some(mut err) = self.demand_eqtype_diag(pat.span, expected, pat_ty) {
+                    err.emit();
+                    // Walk subpatterns with an expected type of `err` in this case to silence
+                    // further errors being emitted when using the bindings. #50333
+                    let element_tys_iter = (0..max_len).map(|_| tcx.types.err);
+                    for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
+                        self.check_pat_walk(elem, &tcx.types.err, def_bm, true);
+                    }
+                    tcx.mk_tup(element_tys_iter)
+                } else {
+                    for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
+                        self.check_pat_walk(elem, &element_tys[i], def_bm, true);
+                    }
+                    pat_ty
                 }
-                pat_ty
             }
             PatKind::Box(ref inner) => {
                 let inner_ty = self.next_ty_var(TypeVariableOrigin::TypeInference(inner.span));
diff --git a/src/libstd/build.rs b/src/libstd/build.rs
index 016e7adb4c9..0831e29bddd 100644
--- a/src/libstd/build.rs
+++ b/src/libstd/build.rs
@@ -97,6 +97,10 @@ fn build_libbacktrace(target: &str) -> Result<(), ()> {
         .file("../libbacktrace/sort.c")
         .file("../libbacktrace/state.c");
 
+    let any_debug = env::var("RUSTC_DEBUGINFO").unwrap_or(String::new()) == "true" ||
+        env::var("RUSTC_DEBUGINFO_LINES").unwrap_or(String::new()) == "true";
+    build.debug(any_debug);
+
     if target.contains("darwin") {
         build.file("../libbacktrace/macho.c");
     } else if target.contains("windows") {
diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs
index 372f3e83e3d..63dd12f782f 100644
--- a/src/libstd/ffi/c_str.rs
+++ b/src/libstd/ffi/c_str.rs
@@ -102,8 +102,8 @@ use sys;
 /// }
 ///
 /// // We are certain that our string doesn't have 0 bytes in the middle,
-/// // so we can .unwrap()
-/// let c_to_print = CString::new("Hello, world!").unwrap();
+/// // so we can .expect()
+/// let c_to_print = CString::new("Hello, world!").expect("CString::new failed");
 /// unsafe {
 ///     my_printer(c_to_print.as_ptr());
 /// }
@@ -175,7 +175,7 @@ pub struct CString {
 ///     unsafe { work_with(data.as_ptr()) }
 /// }
 ///
-/// let s = CString::new("data data data data").unwrap();
+/// let s = CString::new("data data data data").expect("CString::new failed");
 /// work(&s);
 /// ```
 ///
@@ -314,7 +314,7 @@ impl CString {
     ///
     /// extern { fn puts(s: *const c_char); }
     ///
-    /// let to_print = CString::new("Hello!").unwrap();
+    /// let to_print = CString::new("Hello!").expect("CString::new failed");
     /// unsafe {
     ///     puts(to_print.as_ptr());
     /// }
@@ -398,7 +398,7 @@ impl CString {
     ///     fn some_extern_function(s: *mut c_char);
     /// }
     ///
-    /// let c_string = CString::new("Hello!").unwrap();
+    /// let c_string = CString::new("Hello!").expect("CString::new failed");
     /// let raw = c_string.into_raw();
     /// unsafe {
     ///     some_extern_function(raw);
@@ -428,7 +428,7 @@ impl CString {
     /// ```
     /// use std::ffi::CString;
     ///
-    /// let c_string = CString::new("foo").unwrap();
+    /// let c_string = CString::new("foo").expect("CString::new failed");
     ///
     /// let ptr = c_string.into_raw();
     ///
@@ -460,12 +460,12 @@ impl CString {
     /// use std::ffi::CString;
     ///
     /// let valid_utf8 = vec![b'f', b'o', b'o'];
-    /// let cstring = CString::new(valid_utf8).unwrap();
-    /// assert_eq!(cstring.into_string().unwrap(), "foo");
+    /// let cstring = CString::new(valid_utf8).expect("CString::new failed");
+    /// assert_eq!(cstring.into_string().expect("into_string() call failed"), "foo");
     ///
     /// let invalid_utf8 = vec![b'f', 0xff, b'o', b'o'];
-    /// let cstring = CString::new(invalid_utf8).unwrap();
-    /// let err = cstring.into_string().err().unwrap();
+    /// let cstring = CString::new(invalid_utf8).expect("CString::new failed");
+    /// let err = cstring.into_string().err().expect("into_string().err() failed");
     /// assert_eq!(err.utf8_error().valid_up_to(), 1);
     /// ```
 
@@ -489,7 +489,7 @@ impl CString {
     /// ```
     /// use std::ffi::CString;
     ///
-    /// let c_string = CString::new("foo").unwrap();
+    /// let c_string = CString::new("foo").expect("CString::new failed");
     /// let bytes = c_string.into_bytes();
     /// assert_eq!(bytes, vec![b'f', b'o', b'o']);
     /// ```
@@ -511,7 +511,7 @@ impl CString {
     /// ```
     /// use std::ffi::CString;
     ///
-    /// let c_string = CString::new("foo").unwrap();
+    /// let c_string = CString::new("foo").expect("CString::new failed");
     /// let bytes = c_string.into_bytes_with_nul();
     /// assert_eq!(bytes, vec![b'f', b'o', b'o', b'\0']);
     /// ```
@@ -534,7 +534,7 @@ impl CString {
     /// ```
     /// use std::ffi::CString;
     ///
-    /// let c_string = CString::new("foo").unwrap();
+    /// let c_string = CString::new("foo").expect("CString::new failed");
     /// let bytes = c_string.as_bytes();
     /// assert_eq!(bytes, &[b'f', b'o', b'o']);
     /// ```
@@ -554,7 +554,7 @@ impl CString {
     /// ```
     /// use std::ffi::CString;
     ///
-    /// let c_string = CString::new("foo").unwrap();
+    /// let c_string = CString::new("foo").expect("CString::new failed");
     /// let bytes = c_string.as_bytes_with_nul();
     /// assert_eq!(bytes, &[b'f', b'o', b'o', b'\0']);
     /// ```
@@ -573,9 +573,10 @@ impl CString {
     /// ```
     /// use std::ffi::{CString, CStr};
     ///
-    /// let c_string = CString::new(b"foo".to_vec()).unwrap();
+    /// let c_string = CString::new(b"foo".to_vec()).expect("CString::new failed");
     /// let c_str = c_string.as_c_str();
-    /// assert_eq!(c_str, CStr::from_bytes_with_nul(b"foo\0").unwrap());
+    /// assert_eq!(c_str,
+    ///            CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"));
     /// ```
     #[inline]
     #[stable(feature = "as_c_str", since = "1.20.0")]
@@ -592,16 +593,17 @@ impl CString {
     /// ```
     /// use std::ffi::{CString, CStr};
     ///
-    /// let c_string = CString::new(b"foo".to_vec()).unwrap();
+    /// let c_string = CString::new(b"foo".to_vec()).expect("CString::new failed");
     /// let boxed = c_string.into_boxed_c_str();
-    /// assert_eq!(&*boxed, CStr::from_bytes_with_nul(b"foo\0").unwrap());
+    /// assert_eq!(&*boxed,
+    ///            CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"));
     /// ```
     #[stable(feature = "into_boxed_c_str", since = "1.20.0")]
     pub fn into_boxed_c_str(self) -> Box<CStr> {
         unsafe { Box::from_raw(Box::into_raw(self.into_inner()) as *mut CStr) }
     }
 
-    // Bypass "move out of struct which implements [`Drop`] trait" restriction.
+    /// Bypass "move out of struct which implements [`Drop`] trait" restriction.
     ///
     /// [`Drop`]: ../ops/trait.Drop.html
     fn into_inner(self) -> Box<[u8]> {
@@ -1031,7 +1033,7 @@ impl CStr {
     /// use std::ffi::{CStr, CString};
     ///
     /// unsafe {
-    ///     let cstring = CString::new("hello").unwrap();
+    ///     let cstring = CString::new("hello").expect("CString::new failed");
     ///     let cstr = CStr::from_bytes_with_nul_unchecked(cstring.to_bytes_with_nul());
     ///     assert_eq!(cstr, &*cstring);
     /// }
@@ -1058,7 +1060,7 @@ impl CStr {
     /// # #![allow(unused_must_use)]
     /// use std::ffi::{CString};
     ///
-    /// let ptr = CString::new("Hello").unwrap().as_ptr();
+    /// let ptr = CString::new("Hello").expect("CString::new failed").as_ptr();
     /// unsafe {
     ///     // `ptr` is dangling
     ///     *ptr;
@@ -1067,14 +1069,14 @@ impl CStr {
     ///
     /// This happens because the pointer returned by `as_ptr` does not carry any
     /// lifetime information and the [`CString`] is deallocated immediately after
-    /// the `CString::new("Hello").unwrap().as_ptr()` expression is evaluated.
+    /// the `CString::new("Hello").expect("CString::new failed").as_ptr()` expression is evaluated.
     /// To fix the problem, bind the `CString` to a local variable:
     ///
     /// ```no_run
     /// # #![allow(unused_must_use)]
     /// use std::ffi::{CString};
     ///
-    /// let hello = CString::new("Hello").unwrap();
+    /// let hello = CString::new("Hello").expect("CString::new failed");
     /// let ptr = hello.as_ptr();
     /// unsafe {
     ///     // `ptr` is valid because `hello` is in scope
@@ -1106,7 +1108,7 @@ impl CStr {
     /// ```
     /// use std::ffi::CStr;
     ///
-    /// let c_str = CStr::from_bytes_with_nul(b"foo\0").unwrap();
+    /// let c_str = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed");
     /// assert_eq!(c_str.to_bytes(), b"foo");
     /// ```
     #[inline]
@@ -1132,7 +1134,7 @@ impl CStr {
     /// ```
     /// use std::ffi::CStr;
     ///
-    /// let c_str = CStr::from_bytes_with_nul(b"foo\0").unwrap();
+    /// let c_str = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed");
     /// assert_eq!(c_str.to_bytes_with_nul(), b"foo\0");
     /// ```
     #[inline]
@@ -1159,7 +1161,7 @@ impl CStr {
     /// ```
     /// use std::ffi::CStr;
     ///
-    /// let c_str = CStr::from_bytes_with_nul(b"foo\0").unwrap();
+    /// let c_str = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed");
     /// assert_eq!(c_str.to_str(), Ok("foo"));
     /// ```
     #[stable(feature = "cstr_to_str", since = "1.4.0")]
@@ -1200,7 +1202,8 @@ impl CStr {
     /// use std::borrow::Cow;
     /// use std::ffi::CStr;
     ///
-    /// let c_str = CStr::from_bytes_with_nul(b"Hello World\0").unwrap();
+    /// let c_str = CStr::from_bytes_with_nul(b"Hello World\0")
+    ///                  .expect("CStr::from_bytes_with_nul failed");
     /// assert_eq!(c_str.to_string_lossy(), Cow::Borrowed("Hello World"));
     /// ```
     ///
@@ -1210,7 +1213,8 @@ impl CStr {
     /// use std::borrow::Cow;
     /// use std::ffi::CStr;
     ///
-    /// let c_str = CStr::from_bytes_with_nul(b"Hello \xF0\x90\x80World\0").unwrap();
+    /// let c_str = CStr::from_bytes_with_nul(b"Hello \xF0\x90\x80World\0")
+    ///                  .expect("CStr::from_bytes_with_nul failed");
     /// assert_eq!(
     ///     c_str.to_string_lossy(),
     ///     Cow::Owned(String::from("Hello �World")) as Cow<str>
@@ -1231,9 +1235,9 @@ impl CStr {
     /// ```
     /// use std::ffi::CString;
     ///
-    /// let c_string = CString::new(b"foo".to_vec()).unwrap();
+    /// let c_string = CString::new(b"foo".to_vec()).expect("CString::new failed");
     /// let boxed = c_string.into_boxed_c_str();
-    /// assert_eq!(boxed.into_c_string(), CString::new("foo").unwrap());
+    /// assert_eq!(boxed.into_c_string(), CString::new("foo").expect("CString::new failed"));
     /// ```
     #[stable(feature = "into_boxed_c_str", since = "1.20.0")]
     pub fn into_c_string(self: Box<CStr>) -> CString {
diff --git a/src/libsyntax/util/lev_distance.rs b/src/libsyntax/util/lev_distance.rs
index e429791f2bd..feee2422cb6 100644
--- a/src/libsyntax/util/lev_distance.rs
+++ b/src/libsyntax/util/lev_distance.rs
@@ -11,7 +11,7 @@
 use std::cmp;
 use symbol::Symbol;
 
-/// To find the Levenshtein distance between two strings
+/// Find the Levenshtein distance between two strings
 pub fn lev_distance(a: &str, b: &str) -> usize {
     // cases which don't require further computation
     if a.is_empty() {
@@ -41,10 +41,12 @@ pub fn lev_distance(a: &str, b: &str) -> usize {
     } dcol[t_last + 1]
 }
 
-/// To find the best match for a given string from an iterator of names
+/// Find the best match for a given word in the given iterator
+///
 /// As a loose rule to avoid the obviously incorrect suggestions, it takes
 /// an optional limit for the maximum allowable edit distance, which defaults
 /// to one-third of the given word.
+///
 /// Besides Levenshtein, we use case insensitive comparison to improve accuracy on an edge case with
 /// a lower(upper)case letters mismatch.
 pub fn find_best_match_for_name<'a, T>(iter_names: T,
@@ -105,3 +107,39 @@ fn test_lev_distance() {
     assert_eq!(lev_distance(b, c), 1);
     assert_eq!(lev_distance(c, b), 1);
 }
+
+#[test]
+fn test_find_best_match_for_name() {
+    use with_globals;
+    with_globals(|| {
+        let input = vec![Symbol::intern("aaab"), Symbol::intern("aaabc")];
+        assert_eq!(
+            find_best_match_for_name(input.iter(), "aaaa", None),
+            Some(Symbol::intern("aaab"))
+        );
+
+        assert_eq!(
+            find_best_match_for_name(input.iter(), "1111111111", None),
+            None
+        );
+
+        let input = vec![Symbol::intern("aAAA")];
+        assert_eq!(
+            find_best_match_for_name(input.iter(), "AAAA", None),
+            Some(Symbol::intern("aAAA"))
+        );
+
+        let input = vec![Symbol::intern("AAAA")];
+        // Returns None because `lev_distance > max_dist / 3`
+        assert_eq!(
+            find_best_match_for_name(input.iter(), "aaaa", None),
+            None
+        );
+
+        let input = vec![Symbol::intern("AAAA")];
+        assert_eq!(
+            find_best_match_for_name(input.iter(), "aaaa", Some(4)),
+            Some(Symbol::intern("AAAA"))
+        );
+    })
+}
diff --git a/src/stage0.txt b/src/stage0.txt
index a93b25607eb..69e8140cdf1 100644
--- a/src/stage0.txt
+++ b/src/stage0.txt
@@ -12,7 +12,7 @@
 # source tarball for a stable release you'll likely see `1.x.0` for rustc and
 # `0.x.0` for Cargo where they were released on `date`.
 
-date: 2018-08-01
+date: 2018-09-11
 rustc: beta
 cargo: beta
 
diff --git a/src/test/run-make-fulldeps/codegen-options-parsing/Makefile b/src/test/run-make-fulldeps/codegen-options-parsing/Makefile
index fda96a8b1fb..39e9a9bdd6b 100644
--- a/src/test/run-make-fulldeps/codegen-options-parsing/Makefile
+++ b/src/test/run-make-fulldeps/codegen-options-parsing/Makefile
@@ -16,11 +16,11 @@ all:
 	$(RUSTC) -C extra-filename=foo dummy.rs 2>&1
 	#Option taking no argument
 	$(RUSTC) -C lto= dummy.rs 2>&1 | \
-		$(CGREP) 'codegen option `lto` - one of `thin`, `fat`, or'
+		$(CGREP) 'codegen option `lto` - either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted'
 	$(RUSTC) -C lto=1 dummy.rs 2>&1 | \
-		$(CGREP) 'codegen option `lto` - one of `thin`, `fat`, or'
+		$(CGREP) 'codegen option `lto` - either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted'
 	$(RUSTC) -C lto=foo dummy.rs 2>&1 | \
-		$(CGREP) 'codegen option `lto` - one of `thin`, `fat`, or'
+		$(CGREP) 'codegen option `lto` - either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted'
 	$(RUSTC) -C lto dummy.rs
 
 	# Should not link dead code...
diff --git a/src/test/run-make-fulldeps/lto-smoke/Makefile b/src/test/run-make-fulldeps/lto-smoke/Makefile
index 020252e1f8c..9b1dc2550b2 100644
--- a/src/test/run-make-fulldeps/lto-smoke/Makefile
+++ b/src/test/run-make-fulldeps/lto-smoke/Makefile
@@ -1,6 +1,30 @@
 -include ../tools.mk
 
-all:
+all: noparam bool_true bool_false thin fat
+
+noparam:
 	$(RUSTC) lib.rs
 	$(RUSTC) main.rs -C lto
 	$(call RUN,main)
+
+bool_true:
+	$(RUSTC) lib.rs
+	$(RUSTC) main.rs -C lto=yes
+	$(call RUN,main)
+
+
+bool_false:
+	$(RUSTC) lib.rs
+	$(RUSTC) main.rs -C lto=off
+	$(call RUN,main)
+
+thin:
+	$(RUSTC) lib.rs
+	$(RUSTC) main.rs -C lto=thin
+	$(call RUN,main)
+
+fat:
+	$(RUSTC) lib.rs
+	$(RUSTC) main.rs -C lto=fat
+	$(call RUN,main)
+
diff --git a/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs b/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs
new file mode 100644
index 00000000000..d6ffca09e96
--- /dev/null
+++ b/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs
@@ -0,0 +1,37 @@
+// Copyright 2018 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.
+
+// New test for #53818: modifying static memory at compile-time is not allowed.
+// The test should never succeed.
+
+#![feature(const_raw_ptr_deref)]
+#![feature(const_let)]
+
+use std::cell::UnsafeCell;
+
+struct Foo(UnsafeCell<u32>);
+
+unsafe impl Send for Foo {}
+unsafe impl Sync for Foo {}
+
+static FOO: Foo = Foo(UnsafeCell::new(42));
+
+static BAR: () = unsafe {
+    *FOO.0.get() = 5;
+    //~^ ERROR calls in statics are limited to constant functions, tuple structs and tuple variants
+
+    // This error is caused by a separate bug that the feature gate error is reported
+    // even though the feature gate "const_let" is active.
+    //~| statements in statics are unstable (see issue #48821)
+};
+
+fn main() {
+    println!("{}", unsafe { *FOO.0.get() });
+}
diff --git a/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr b/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr
new file mode 100644
index 00000000000..8eaed1dcab1
--- /dev/null
+++ b/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr
@@ -0,0 +1,18 @@
+error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
+  --> $DIR/mod-static-with-const-fn.rs:27:6
+   |
+LL |     *FOO.0.get() = 5;
+   |      ^^^^^^^^^^^
+
+error[E0658]: statements in statics are unstable (see issue #48821)
+  --> $DIR/mod-static-with-const-fn.rs:27:5
+   |
+LL |     *FOO.0.get() = 5;
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0015, E0658.
+For more information about an error, try `rustc --explain E0015`.
diff --git a/src/test/ui/consts/const-size_of-cycle.rs b/src/test/ui/consts/const-size_of-cycle.rs
index 04c054f8b6d..1ea7b973c46 100644
--- a/src/test/ui/consts/const-size_of-cycle.rs
+++ b/src/test/ui/consts/const-size_of-cycle.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-musl
+// ignore-x86
 // error-pattern: cycle detected
 
 struct Foo {
diff --git a/src/test/ui/elide-errors-on-mismatched-tuple.rs b/src/test/ui/elide-errors-on-mismatched-tuple.rs
new file mode 100644
index 00000000000..68e579788bc
--- /dev/null
+++ b/src/test/ui/elide-errors-on-mismatched-tuple.rs
@@ -0,0 +1,28 @@
+// Copyright 2018 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.
+
+// Hide irrelevant E0277 errors (#50333)
+
+trait T {}
+
+struct A;
+impl T for A {}
+impl A {
+    fn new() -> Self {
+        Self {}
+    }
+}
+
+fn main() {
+    let (a, b, c) = (A::new(), A::new()); // This tuple is 2 elements, should be three
+    //~^ ERROR mismatched types
+    let ts: Vec<&T> = vec![&a, &b, &c];
+    // There is no E0277 error above, as `a`, `b` and `c` are `TyErr`
+}
diff --git a/src/test/ui/elide-errors-on-mismatched-tuple.stderr b/src/test/ui/elide-errors-on-mismatched-tuple.stderr
new file mode 100644
index 00000000000..b901175d534
--- /dev/null
+++ b/src/test/ui/elide-errors-on-mismatched-tuple.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/elide-errors-on-mismatched-tuple.rs:24:9
+   |
+LL |     let (a, b, c) = (A::new(), A::new()); // This tuple is 2 elements, should be three
+   |         ^^^^^^^^^ expected a tuple with 2 elements, found one with 3 elements
+   |
+   = note: expected type `(A, A)`
+              found type `(_, _, _)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/impl-trait/impl-generic-mismatch.rs b/src/test/ui/impl-trait/impl-generic-mismatch.rs
index d6707f59011..6cf8000f6ad 100644
--- a/src/test/ui/impl-trait/impl-generic-mismatch.rs
+++ b/src/test/ui/impl-trait/impl-generic-mismatch.rs
@@ -8,6 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-musl
+// ignore-x86
+
 use std::fmt::Debug;
 
 trait Foo {
diff --git a/src/test/ui/impl-trait/impl-generic-mismatch.stderr b/src/test/ui/impl-trait/impl-generic-mismatch.stderr
index 7ad16b1f8f2..d777779a881 100644
--- a/src/test/ui/impl-trait/impl-generic-mismatch.stderr
+++ b/src/test/ui/impl-trait/impl-generic-mismatch.stderr
@@ -1,5 +1,5 @@
 error[E0643]: method `foo` has incompatible signature for trait
-  --> $DIR/impl-generic-mismatch.rs:18:12
+  --> $DIR/impl-generic-mismatch.rs:21:12
    |
 LL |     fn foo(&self, _: &impl Debug);
    |                       ---------- declaration in trait here
@@ -12,7 +12,7 @@ LL |     fn foo(&self, _: &impl Debug) { }
    |          --           ^^^^^^^^^^
 
 error[E0643]: method `bar` has incompatible signature for trait
-  --> $DIR/impl-generic-mismatch.rs:27:23
+  --> $DIR/impl-generic-mismatch.rs:30:23
    |
 LL |     fn bar<U: Debug>(&self, _: &U);
    |            - declaration in trait here
@@ -25,7 +25,7 @@ LL |     fn bar<U: Debug>(&self, _: &U) { }
    |           ^^^^^^^^^^            ^
 
 error[E0643]: method `hash` has incompatible signature for trait
-  --> $DIR/impl-generic-mismatch.rs:38:33
+  --> $DIR/impl-generic-mismatch.rs:41:33
    |
 LL |     fn hash(&self, hasher: &mut impl Hasher) {}
    |                                 ^^^^^^^^^^^ expected generic parameter, found `impl Trait`