about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-01-23 16:13:18 +0000
committerbors <bors@rust-lang.org>2018-01-23 16:13:18 +0000
commit4e3901d35f6a8652f67111e7272263c9e62ab3e1 (patch)
tree1cb65ccb8e82d573d3c0d366da563cbe81b8cd1e /src
parent3a39b2aa5a68dd07aacab2106db3927f666a485a (diff)
parent9707b3107612599f8f96facdcd8959669b630e02 (diff)
downloadrust-4e3901d35f6a8652f67111e7272263c9e62ab3e1.tar.gz
rust-4e3901d35f6a8652f67111e7272263c9e62ab3e1.zip
Auto merge of #47678 - kennytm:rollup, r=kennytm
Rollup of 14 pull requests

- Successful merges: #47423, #47425, #47440, #47541, #47549, #47554, #47558, #47610, #47635, #47655, #47661, #47662, #47667, #47672
- Failed merges:
Diffstat (limited to 'src')
-rw-r--r--src/Cargo.lock6
-rw-r--r--src/bootstrap/check.rs1
-rw-r--r--src/bootstrap/flags.rs17
-rw-r--r--src/liballoc_jemalloc/build.rs13
-rw-r--r--src/librustc/ich/hcx.rs21
-rw-r--r--src/librustc/ich/mod.rs2
-rw-r--r--src/librustc/session/config.rs36
-rw-r--r--src/librustc/session/mod.rs6
-rw-r--r--src/librustc_driver/driver.rs30
-rw-r--r--src/librustc_driver/lib.rs36
-rw-r--r--src/librustc_driver/pretty.rs8
-rw-r--r--src/librustc_llvm/ffi.rs2
-rw-r--r--src/librustc_trans/cabi_sparc64.rs7
-rw-r--r--src/librustc_trans/mir/mod.rs2
-rw-r--r--src/librustdoc/clean/inline.rs2
-rw-r--r--src/librustdoc/clean/mod.rs11
-rw-r--r--src/librustdoc/doctree.rs1
-rw-r--r--src/librustdoc/html/render.rs3
-rw-r--r--src/librustdoc/html/static/main.js4
-rw-r--r--src/librustdoc/visit_ast.rs3
-rw-r--r--src/libsyntax_ext/proc_macro_registrar.rs2
-rw-r--r--src/rustllvm/RustWrapper.cpp9
-rw-r--r--src/test/compile-fail/issue-37665.rs2
-rw-r--r--src/test/compile-fail/mir-unpretty.rs2
-rw-r--r--src/test/compile-fail/nll/constant-thread-locals-issue-47053.rs21
-rw-r--r--src/test/run-make/hir-tree/Makefile3
-rw-r--r--src/test/run-make/pretty-print-path-suffix/Makefile6
-rw-r--r--src/test/run-pass-fulldeps/proc-macro/auxiliary/empty-crate.rs14
-rw-r--r--src/test/run-pass-fulldeps/proc-macro/empty-crate.rs17
-rw-r--r--src/test/run-pass/dynamic-drop.rs3
-rw-r--r--src/test/rustdoc-js/quoted.js23
-rw-r--r--src/test/rustdoc/auto-traits.rs23
-rw-r--r--src/test/rustdoc/auxiliary/auto-traits.rs13
-rw-r--r--src/test/ui/issue-29723.rs26
-rw-r--r--src/test/ui/issue-29723.stderr13
-rw-r--r--src/tools/compiletest/src/runtest.rs3
-rw-r--r--src/tools/rustbook/Cargo.toml2
-rw-r--r--src/tools/rustbook/src/main.rs12
38 files changed, 302 insertions, 103 deletions
diff --git a/src/Cargo.lock b/src/Cargo.lock
index 6f919fd1acd..ae9e755b7a0 100644
--- a/src/Cargo.lock
+++ b/src/Cargo.lock
@@ -1108,7 +1108,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "mdbook"
-version = "0.0.26"
+version = "0.0.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1674,7 +1674,7 @@ name = "rustbook"
 version = "0.1.0"
 dependencies = [
  "clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "mdbook 0.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mdbook 0.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2980,7 +2980,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
 "checksum markup5ever 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "047150a0e03b57e638fc45af33a0b63a0362305d5b9f92ecef81df472a4cceb0"
 "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376"
-"checksum mdbook 0.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "8a1ac668292d1e5c7b1c6fd64f70d3a85105b8069a89558a0d67bdb2ff298ca1"
+"checksum mdbook 0.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "1ee8ba20c002000546681dc78d7f7e91fd35832058b1e2fdd492ca842bb6e9be"
 "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20"
 "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
 "checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4"
diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs
index 1187376e177..5faec279438 100644
--- a/src/bootstrap/check.rs
+++ b/src/bootstrap/check.rs
@@ -792,6 +792,7 @@ impl Step for Compiletest {
             flags.push("-g".to_string());
         }
         flags.push("-Zmiri -Zunstable-options".to_string());
+        flags.push(build.config.cmd.rustc_args().join(" "));
 
         if let Some(linker) = build.linker(target) {
             cmd.arg("--linker").arg(linker);
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index b5d51598fab..0816c4dfe3d 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -54,6 +54,7 @@ pub enum Subcommand {
     Test {
         paths: Vec<PathBuf>,
         test_args: Vec<String>,
+        rustc_args: Vec<String>,
         fail_fast: bool,
     },
     Bench {
@@ -150,6 +151,12 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`");
             "test"  => {
                 opts.optflag("", "no-fail-fast", "Run all tests regardless of failure");
                 opts.optmulti("", "test-args", "extra arguments", "ARGS");
+                opts.optmulti(
+                    "",
+                    "rustc-args",
+                    "extra options to pass the compiler when running tests",
+                    "ARGS",
+                );
             },
             "bench" => { opts.optmulti("", "test-args", "extra arguments", "ARGS"); },
             "clean" => { opts.optflag("", "all", "clean all build artifacts"); },
@@ -283,6 +290,7 @@ Arguments:
                 Subcommand::Test {
                     paths,
                     test_args: matches.opt_strs("test-args"),
+                    rustc_args: matches.opt_strs("rustc-args"),
                     fail_fast: !matches.opt_present("no-fail-fast"),
                 }
             }
@@ -362,6 +370,15 @@ impl Subcommand {
         }
     }
 
+    pub fn rustc_args(&self) -> Vec<&str> {
+        match *self {
+            Subcommand::Test { ref rustc_args, .. } => {
+                rustc_args.iter().flat_map(|s| s.split_whitespace()).collect()
+            }
+            _ => Vec::new(),
+        }
+    }
+
     pub fn fail_fast(&self) -> bool {
         match *self {
             Subcommand::Test { fail_fast, .. } => fail_fast,
diff --git a/src/liballoc_jemalloc/build.rs b/src/liballoc_jemalloc/build.rs
index 440c9fbf2f6..0aa46dc6d20 100644
--- a/src/liballoc_jemalloc/build.rs
+++ b/src/liballoc_jemalloc/build.rs
@@ -29,13 +29,20 @@ fn main() {
     // for targets like emscripten, even if we don't use it.
     let target = env::var("TARGET").expect("TARGET was not set");
     let host = env::var("HOST").expect("HOST was not set");
-    if target.contains("bitrig") || target.contains("cloudabi") || target.contains("emscripten") ||
-       target.contains("fuchsia") || target.contains("msvc") || target.contains("openbsd") ||
-       target.contains("redox") || target.contains("rumprun") || target.contains("wasm32") {
+    if target.contains("bitrig") || target.contains("emscripten") || target.contains("fuchsia") ||
+       target.contains("msvc") || target.contains("openbsd") || target.contains("redox") ||
+       target.contains("rumprun") || target.contains("wasm32") {
         println!("cargo:rustc-cfg=dummy_jemalloc");
         return;
     }
 
+    // CloudABI ships with a copy of jemalloc that has been patched to
+    // work well with sandboxing. Don't attempt to build our own copy,
+    // as it won't build.
+    if target.contains("cloudabi") {
+        return;
+    }
+
     if target.contains("android") {
         println!("cargo:rustc-link-lib=gcc");
     } else if !target.contains("windows") && !target.contains("musl") {
diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs
index 2945b1ab912..67f6c0c2e49 100644
--- a/src/librustc/ich/hcx.rs
+++ b/src/librustc/ich/hcx.rs
@@ -19,8 +19,8 @@ use session::Session;
 
 use std::cmp::Ord;
 use std::hash as std_hash;
-use std::cell::RefCell;
 use std::collections::HashMap;
+use std::cell::RefCell;
 
 use syntax::ast;
 
@@ -36,8 +36,10 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHashingContextProvi
 use rustc_data_structures::accumulate_vec::AccumulateVec;
 use rustc_data_structures::fx::{FxHashSet, FxHashMap};
 
-thread_local!(static IGNORED_ATTR_NAMES: RefCell<FxHashSet<Symbol>> =
-    RefCell::new(FxHashSet()));
+pub fn compute_ignored_attr_names() -> FxHashSet<Symbol> {
+    debug_assert!(ich::IGNORED_ATTRIBUTES.len() > 0);
+    ich::IGNORED_ATTRIBUTES.iter().map(|&s| Symbol::intern(s)).collect()
+}
 
 /// This is the context state available during incr. comp. hashing. It contains
 /// enough information to transform DefIds and HirIds into stable DefPaths (i.e.
@@ -90,15 +92,6 @@ impl<'gcx> StableHashingContext<'gcx> {
                -> Self {
         let hash_spans_initial = !sess.opts.debugging_opts.incremental_ignore_spans;
 
-        debug_assert!(ich::IGNORED_ATTRIBUTES.len() > 0);
-        IGNORED_ATTR_NAMES.with(|names| {
-            let mut names = names.borrow_mut();
-            if names.is_empty() {
-                names.extend(ich::IGNORED_ATTRIBUTES.iter()
-                                                    .map(|&s| Symbol::intern(s)));
-            }
-        });
-
         StableHashingContext {
             sess,
             body_resolver: BodyResolver(krate),
@@ -186,9 +179,7 @@ impl<'gcx> StableHashingContext<'gcx> {
 
     #[inline]
     pub fn is_ignored_attr(&self, name: Symbol) -> bool {
-        IGNORED_ATTR_NAMES.with(|names| {
-            names.borrow().contains(&name)
-        })
+        self.sess.ignored_attr_names.contains(&name)
     }
 
     pub fn hash_hir_item_like<F: FnOnce(&mut Self)>(&mut self, f: F) {
diff --git a/src/librustc/ich/mod.rs b/src/librustc/ich/mod.rs
index cbd76ee14db..ce1bd07b14c 100644
--- a/src/librustc/ich/mod.rs
+++ b/src/librustc/ich/mod.rs
@@ -13,7 +13,7 @@
 pub use self::fingerprint::Fingerprint;
 pub use self::caching_codemap_view::CachingCodemapView;
 pub use self::hcx::{StableHashingContext, NodeIdHashingMode,
-                    hash_stable_trait_impls};
+                    hash_stable_trait_impls, compute_ignored_attr_names};
 mod fingerprint;
 mod caching_codemap_view;
 mod hcx;
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index cd4e3cfed7a..da119ba4569 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -778,6 +778,8 @@ macro_rules! options {
             Some(::rustc_back::LinkerFlavor::one_of());
         pub const parse_optimization_fuel: Option<&'static str> =
             Some("crate=integer");
+        pub const parse_unpretty: Option<&'static str> =
+            Some("`string` or `string=string`");
     }
 
     #[allow(dead_code)]
@@ -965,6 +967,17 @@ macro_rules! options {
                 }
             }
         }
+
+        fn parse_unpretty(slot: &mut Option<String>, v: Option<&str>) -> bool {
+            match v {
+                None => false,
+                Some(s) if s.split('=').count() <= 2 => {
+                    *slot = Some(s.to_string());
+                    true
+                }
+                _ => false,
+            }
+        }
     }
 ) }
 
@@ -1104,13 +1117,13 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
         "write syntax and type analysis (in JSON format) information, in \
          addition to normal output"),
     flowgraph_print_loans: bool = (false, parse_bool, [UNTRACKED],
-        "include loan analysis data in --unpretty flowgraph output"),
+        "include loan analysis data in -Z unpretty flowgraph output"),
     flowgraph_print_moves: bool = (false, parse_bool, [UNTRACKED],
-        "include move analysis data in --unpretty flowgraph output"),
+        "include move analysis data in -Z unpretty flowgraph output"),
     flowgraph_print_assigns: bool = (false, parse_bool, [UNTRACKED],
-        "include assignment analysis data in --unpretty flowgraph output"),
+        "include assignment analysis data in -Z unpretty flowgraph output"),
     flowgraph_print_all: bool = (false, parse_bool, [UNTRACKED],
-        "include all dataflow analysis data in --unpretty flowgraph output"),
+        "include all dataflow analysis data in -Z unpretty flowgraph output"),
     print_region_graph: bool = (false, parse_bool, [UNTRACKED],
          "prints region inference graph. \
           Use with RUST_REGION_GRAPH=help for more info"),
@@ -1241,6 +1254,13 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
     dep_info_omit_d_target: bool = (false, parse_bool, [TRACKED],
         "in dep-info output, omit targets for tracking dependencies of the dep-info files \
          themselves"),
+    unpretty: Option<String> = (None, parse_unpretty, [UNTRACKED],
+        "Present the input source, unstable (and less-pretty) variants;
+        valid types are any of the types for `--pretty`, as well as:
+        `flowgraph=<nodeid>` (graphviz formatted flowgraph for node),
+        `everybody_loops` (all function bodies replaced with `loop {}`),
+        `hir` (the HIR), `hir,identified`, or
+        `hir,typed` (HIR with types for each node)."),
 }
 
 pub fn default_lib_output() -> CrateType {
@@ -1514,14 +1534,6 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
                   `expanded` (crates expanded), or
                   `expanded,identified` (fully parenthesized, AST nodes with IDs).",
                  "TYPE"),
-        opt::opt("", "unpretty",
-                 "Present the input source, unstable (and less-pretty) variants;
-                  valid types are any of the types for `--pretty`, as well as:
-                  `flowgraph=<nodeid>` (graphviz formatted flowgraph for node),
-                  `everybody_loops` (all function bodies replaced with `loop {}`),
-                  `hir` (the HIR), `hir,identified`, or
-                  `hir,typed` (HIR with types for each node).",
-                 "TYPE"),
     ]);
     opts
 }
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index 94fcfb7e2aa..36f716a4a76 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -14,6 +14,7 @@ pub use self::code_stats::{SizeKind, TypeSizeInfo, VariantInfo};
 use hir::def_id::CrateNum;
 use ich::Fingerprint;
 
+use ich;
 use lint;
 use middle::allocator::AllocatorKind;
 use middle::dependency_format;
@@ -28,6 +29,7 @@ use errors::{self, DiagnosticBuilder, DiagnosticId};
 use errors::emitter::{Emitter, EmitterWriter};
 use syntax::json::JsonEmitter;
 use syntax::feature_gate;
+use syntax::symbol::Symbol;
 use syntax::parse;
 use syntax::parse::ParseSess;
 use syntax::{ast, codemap};
@@ -112,6 +114,9 @@ pub struct Session {
 
     incr_comp_session: RefCell<IncrCompSession>,
 
+    /// A cache of attributes ignored by StableHashingContext
+    pub ignored_attr_names: FxHashSet<Symbol>,
+
     /// Some measurements that are being gathered during compilation.
     pub perf_stats: PerfStats,
 
@@ -975,6 +980,7 @@ pub fn build_session_(sopts: config::Options,
         injected_panic_runtime: Cell::new(None),
         imported_macro_spans: RefCell::new(HashMap::new()),
         incr_comp_session: RefCell::new(IncrCompSession::NotInitialized),
+        ignored_attr_names: ich::compute_ignored_attr_names(),
         perf_stats: PerfStats {
             svh_time: Cell::new(Duration::from_secs(0)),
             incr_comp_hashes_time: Cell::new(Duration::from_secs(0)),
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index b2897bd4548..e97d83ed1ee 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -51,14 +51,12 @@ use std::iter;
 use std::path::{Path, PathBuf};
 use std::rc::Rc;
 use std::sync::mpsc;
-use syntax::{ast, diagnostics, visit};
-use syntax::attr;
+use syntax::{self, ast, attr, diagnostics, visit};
 use syntax::ext::base::ExtCtxt;
 use syntax::fold::Folder;
 use syntax::parse::{self, PResult};
 use syntax::util::node_count::NodeCounter;
 use syntax_pos::FileName;
-use syntax;
 use syntax_ext;
 
 use derive_registrar;
@@ -275,10 +273,6 @@ pub fn compile_input(trans: Box<TransCrate>,
     Ok(())
 }
 
-fn keep_hygiene_data(sess: &Session) -> bool {
-    sess.opts.debugging_opts.keep_hygiene_data
-}
-
 pub fn source_name(input: &Input) -> FileName {
     match *input {
         Input::File(ref ifile) => ifile.clone().into(),
@@ -900,7 +894,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session,
          || lint::check_ast_crate(sess, &krate));
 
     // Discard hygiene data, which isn't required after lowering to HIR.
-    if !keep_hygiene_data(sess) {
+    if !sess.opts.debugging_opts.keep_hygiene_data {
         syntax::ext::hygiene::clear_markings();
     }
 
@@ -952,18 +946,6 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(trans: &TransCrate,
                             mpsc::Receiver<Box<Any + Send>>,
                             CompileResult) -> R
 {
-    macro_rules! try_with_f {
-        ($e: expr, ($($t:tt)*)) => {
-            match $e {
-                Ok(x) => x,
-                Err(x) => {
-                    f($($t)*, Err(x));
-                    return Err(x);
-                }
-            }
-        }
-    }
-
     let time_passes = sess.time_passes();
 
     let query_result_on_disk_cache = time(time_passes,
@@ -1024,7 +1006,13 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(trans: &TransCrate,
              || stability::check_unstable_api_usage(tcx));
 
         // passes are timed inside typeck
-        try_with_f!(typeck::check_crate(tcx), (tcx, analysis, rx));
+        match typeck::check_crate(tcx) {
+            Ok(x) => x,
+            Err(x) => {
+                f(tcx, analysis, rx, Err(x));
+                return Err(x);
+            }
+        }
 
         time(time_passes,
              "const checking",
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index de5559c8b14..04e94979c71 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -347,8 +347,9 @@ fn parse_pretty(sess: &Session,
     } else {
         None
     };
-    if pretty.is_none() && sess.unstable_options() {
-        matches.opt_str("unpretty").map(|a| {
+
+    if pretty.is_none() {
+        sess.opts.debugging_opts.unpretty.as_ref().map(|a| {
             // extended with unstable pretty-print variants
             pretty::parse_pretty(sess, &a, true)
         })
@@ -669,7 +670,7 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
             control.after_hir_lowering.stop = Compilation::Stop;
         }
 
-        if save_analysis(sess) {
+        if sess.opts.debugging_opts.save_analysis {
             enable_save_analysis(&mut control);
         }
 
@@ -704,10 +705,6 @@ pub fn enable_save_analysis(control: &mut CompileController) {
     control.make_glob_map = resolve::MakeGlobMap::Yes;
 }
 
-fn save_analysis(sess: &Session) -> bool {
-    sess.opts.debugging_opts.save_analysis
-}
-
 impl RustcDefaultCalls {
     pub fn list_metadata(sess: &Session,
                          cstore: &CrateStore,
@@ -1329,20 +1326,19 @@ pub fn diagnostics_registry() -> errors::registry::Registry {
     Registry::new(&all_errors)
 }
 
-pub fn get_args() -> Vec<String> {
-    env::args_os().enumerate()
-        .map(|(i, arg)| arg.into_string().unwrap_or_else(|arg| {
-             early_error(ErrorOutputType::default(),
-                         &format!("Argument {} is not valid Unicode: {:?}", i, arg))
-         }))
-        .collect()
-}
-
 pub fn main() {
     env_logger::init().unwrap();
-    let result = run(|| run_compiler(&get_args(),
-                                     &mut RustcDefaultCalls,
-                                     None,
-                                     None));
+    let result = run(|| {
+        let args = env::args_os().enumerate()
+            .map(|(i, arg)| arg.into_string().unwrap_or_else(|arg| {
+                early_error(ErrorOutputType::default(),
+                            &format!("Argument {} is not valid Unicode: {:?}", i, arg))
+            }))
+            .collect::<Vec<_>>();
+        run_compiler(&args,
+                     &mut RustcDefaultCalls,
+                     None,
+                     None)
+    });
     process::exit(result as i32);
 }
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index af3d1e4d4d0..68f4b17a6a3 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -66,7 +66,7 @@ pub enum PpSourceMode {
 pub enum PpFlowGraphMode {
     Default,
     /// Drops the labels from the edges in the flowgraph output. This
-    /// is mostly for use in the --unpretty flowgraph run-make tests,
+    /// is mostly for use in the -Z unpretty flowgraph run-make tests,
     /// since the labels are largely uninteresting in those cases and
     /// have become a pain to maintain.
     UnlabelledEdges,
@@ -1007,7 +1007,7 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session,
                                            move |annotation, _| {
                     debug!("pretty printing source code {:?}", s);
                     let sess = annotation.sess();
-                    let hir_map = annotation.hir_map().expect("--unpretty missing HIR map");
+                    let hir_map = annotation.hir_map().expect("-Z unpretty missing HIR map");
                     let mut pp_state = pprust_hir::State::new_from_input(sess.codemap(),
                                                                          &sess.parse_sess,
                                                                          src_name,
@@ -1020,7 +1020,7 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session,
                         pp_state.print_node(node)?;
                         pp_state.s.space()?;
                         let path = annotation.node_path(node_id)
-                            .expect("--unpretty missing node paths");
+                            .expect("-Z unpretty missing node paths");
                         pp_state.synth_comment(path)?;
                         pp_state.s.hardbreak()?;
                     }
@@ -1072,7 +1072,7 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session,
                                        ofile: Option<&Path>) {
     let nodeid = if let Some(uii) = uii {
         debug!("pretty printing for {:?}", uii);
-        Some(uii.to_one_node_id("--unpretty", sess, &hir_map))
+        Some(uii.to_one_node_id("-Z unpretty", sess, &hir_map))
     } else {
         debug!("pretty printing for whole crate");
         None
diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs
index b97e37f4c8f..f51e51a88b1 100644
--- a/src/librustc_llvm/ffi.rs
+++ b/src/librustc_llvm/ffi.rs
@@ -1546,7 +1546,7 @@ extern "C" {
                                                 InlinedAt: MetadataRef)
                                                 -> ValueRef;
     pub fn LLVMRustDIBuilderCreateOpDeref() -> i64;
-    pub fn LLVMRustDIBuilderCreateOpPlus() -> i64;
+    pub fn LLVMRustDIBuilderCreateOpPlusUconst() -> i64;
 
     pub fn LLVMRustWriteTypeToString(Type: TypeRef, s: RustStringRef);
     pub fn LLVMRustWriteValueToString(value_ref: ValueRef, s: RustStringRef);
diff --git a/src/librustc_trans/cabi_sparc64.rs b/src/librustc_trans/cabi_sparc64.rs
index fb94b09d626..b3fc6a68061 100644
--- a/src/librustc_trans/cabi_sparc64.rs
+++ b/src/librustc_trans/cabi_sparc64.rs
@@ -50,7 +50,7 @@ fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>)
     }
     let size = ret.layout.size;
     let bits = size.bits();
-    if bits <= 128 {
+    if bits <= 256 {
         let unit = if bits <= 8 {
             Reg::i8()
         } else if bits <= 16 {
@@ -84,6 +84,11 @@ fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>)
     }
 
     let total = arg.layout.size;
+    if total.bits() > 128 {
+        arg.make_indirect();
+        return;
+    }
+
     arg.cast_to(Uniform {
         unit: Reg::i64(),
         total
diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs
index 3064e2f7c7a..b367eb6548d 100644
--- a/src/librustc_trans/mir/mod.rs
+++ b/src/librustc_trans/mir/mod.rs
@@ -547,7 +547,7 @@ fn arg_local_refs<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
 
                 let ops = unsafe {
                     [llvm::LLVMRustDIBuilderCreateOpDeref(),
-                     llvm::LLVMRustDIBuilderCreateOpPlus(),
+                     llvm::LLVMRustDIBuilderCreateOpPlusUconst(),
                      byte_offset_of_var_in_env as i64,
                      llvm::LLVMRustDIBuilderCreateOpDeref()]
                 };
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index e4e3cc2acd5..9aba399b3b0 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -150,12 +150,14 @@ pub fn build_external_trait(cx: &DocContext, did: DefId) -> clean::Trait {
     let generics = filter_non_trait_generics(did, generics);
     let (generics, supertrait_bounds) = separate_supertrait_bounds(generics);
     let is_spotlight = load_attrs(cx, did).has_doc_flag("spotlight");
+    let is_auto = cx.tcx.trait_is_auto(did);
     clean::Trait {
         unsafety: cx.tcx.trait_def(did).unsafety,
         generics,
         items: trait_items,
         bounds: supertrait_bounds,
         is_spotlight,
+        is_auto,
     }
 }
 
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index fb1d21d6527..ed6b12d65d9 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1800,6 +1800,7 @@ pub struct Trait {
     pub generics: Generics,
     pub bounds: Vec<TyParamBound>,
     pub is_spotlight: bool,
+    pub is_auto: bool,
 }
 
 impl Clean<Item> for doctree::Trait {
@@ -1820,11 +1821,21 @@ impl Clean<Item> for doctree::Trait {
                 generics: self.generics.clean(cx),
                 bounds: self.bounds.clean(cx),
                 is_spotlight: is_spotlight,
+                is_auto: self.is_auto.clean(cx),
             }),
         }
     }
 }
 
+impl Clean<bool> for hir::IsAuto {
+    fn clean(&self, _: &DocContext) -> bool {
+        match *self {
+            hir::IsAuto::Yes => true,
+            hir::IsAuto::No => false,
+        }
+    }
+}
+
 impl Clean<Type> for hir::TraitRef {
     fn clean(&self, cx: &DocContext) -> Type {
         resolve_type(cx, self.path.clean(cx), self.ref_id)
diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs
index 776ec7f409c..430236f30c4 100644
--- a/src/librustdoc/doctree.rs
+++ b/src/librustdoc/doctree.rs
@@ -196,6 +196,7 @@ pub struct Constant {
 }
 
 pub struct Trait {
+    pub is_auto: hir::IsAuto,
     pub unsafety: hir::Unsafety,
     pub name: Name,
     pub items: hir::HirVec<hir::TraitItem>,
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index e4878d6b631..b0d535d9df6 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -2423,9 +2423,10 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
     // Output the trait definition
     write!(w, "<pre class='rust trait'>")?;
     render_attributes(w, it)?;
-    write!(w, "{}{}trait {}{}{}",
+    write!(w, "{}{}{}trait {}{}{}",
            VisSpace(&it.visibility),
            UnsafetySpace(t.unsafety),
+           if t.is_auto { "auto " } else { "" },
            it.name.as_ref().unwrap(),
            t.generics,
            bounds)?;
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index 659bed18b00..0f9e7001c15 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -608,7 +608,7 @@
                 var lev_distance = MAX_LEV_DISTANCE + 1;
                 if (obj.name === val.name) {
                     if (literalSearch === true) {
-                        if (val.generics.length !== 0) {
+                        if (val.generics && val.generics.length !== 0) {
                             if (obj.generics && obj.length >= val.generics.length) {
                                 var elems = obj.generics.slice(0);
                                 var allFound = true;
@@ -645,7 +645,7 @@
                 }
                 // Names didn't match so let's check if one of the generic types could.
                 if (literalSearch === true) {
-                     if (obj.generics.length > 0) {
+                     if (obj.generics && obj.generics.length > 0) {
                         for (var x = 0; x < obj.generics.length; ++x) {
                             if (obj.generics[x] === val.name) {
                                 return true;
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 7b208465369..3b882827c61 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -494,11 +494,12 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> {
                 };
                 om.constants.push(s);
             },
-            hir::ItemTrait(_, unsafety, ref gen, ref b, ref item_ids) => {
+            hir::ItemTrait(is_auto, unsafety, ref gen, ref b, ref item_ids) => {
                 let items = item_ids.iter()
                                     .map(|ti| self.cx.tcx.hir.trait_item(ti.id).clone())
                                     .collect();
                 let t = Trait {
+                    is_auto,
                     unsafety,
                     name,
                     items,
diff --git a/src/libsyntax_ext/proc_macro_registrar.rs b/src/libsyntax_ext/proc_macro_registrar.rs
index 8c5276e1d74..0ba21e6b366 100644
--- a/src/libsyntax_ext/proc_macro_registrar.rs
+++ b/src/libsyntax_ext/proc_macro_registrar.rs
@@ -381,7 +381,7 @@ fn mk_registrar(cx: &mut ExtCtxt,
 
     let __internal = Ident::from_str("__internal");
     let registry = Ident::from_str("Registry");
-    let registrar = Ident::from_str("registrar");
+    let registrar = Ident::from_str("_registrar");
     let register_custom_derive = Ident::from_str("register_custom_derive");
     let register_attr_proc_macro = Ident::from_str("register_attr_proc_macro");
     let register_bang_proc_macro = Ident::from_str("register_bang_proc_macro");
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index 95130d596e1..0fe533d447b 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -866,7 +866,14 @@ extern "C" int64_t LLVMRustDIBuilderCreateOpDeref() {
   return dwarf::DW_OP_deref;
 }
 
-extern "C" int64_t LLVMRustDIBuilderCreateOpPlus() { return dwarf::DW_OP_plus; }
+extern "C" int64_t LLVMRustDIBuilderCreateOpPlusUconst() {
+#if LLVM_VERSION_GE(5, 0)
+  return dwarf::DW_OP_plus_uconst;
+#else
+  // older LLVM used `plus` to behave like `plus_uconst`.
+  return dwarf::DW_OP_plus;
+#endif
+}
 
 extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Ty, RustStringRef Str) {
   RawRustStringOstream OS(Str);
diff --git a/src/test/compile-fail/issue-37665.rs b/src/test/compile-fail/issue-37665.rs
index 98e62965235..81ed4375e77 100644
--- a/src/test/compile-fail/issue-37665.rs
+++ b/src/test/compile-fail/issue-37665.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -Z unstable-options --unpretty=mir
+// compile-flags: -Z unpretty=mir
 // ignore-cloudabi no std::path
 
 use std::path::MAIN_SEPARATOR;
diff --git a/src/test/compile-fail/mir-unpretty.rs b/src/test/compile-fail/mir-unpretty.rs
index 8950bef6a46..fa936502157 100644
--- a/src/test/compile-fail/mir-unpretty.rs
+++ b/src/test/compile-fail/mir-unpretty.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -Z unstable-options --unpretty=mir
+// compile-flags: -Z unpretty=mir
 
 fn main() {
     let x: () = 0; //~ ERROR: mismatched types
diff --git a/src/test/compile-fail/nll/constant-thread-locals-issue-47053.rs b/src/test/compile-fail/nll/constant-thread-locals-issue-47053.rs
new file mode 100644
index 00000000000..c7dc84c1a91
--- /dev/null
+++ b/src/test/compile-fail/nll/constant-thread-locals-issue-47053.rs
@@ -0,0 +1,21 @@
+// 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.
+
+// Regression test for issue #47053
+
+#![feature(nll)]
+#![feature(thread_local)]
+
+#[thread_local]
+static FOO: isize = 5;
+
+fn main() {
+    FOO = 6; //~ ERROR cannot assign to immutable item `FOO` [E0594]
+}
diff --git a/src/test/run-make/hir-tree/Makefile b/src/test/run-make/hir-tree/Makefile
index bedb2b7d6aa..2e100b269e1 100644
--- a/src/test/run-make/hir-tree/Makefile
+++ b/src/test/run-make/hir-tree/Makefile
@@ -4,6 +4,5 @@
 # the string constant we would expect to see.
 
 all:
-	$(RUSTC) -o $(TMPDIR)/input.hir -Z unstable-options \
-		--unpretty=hir-tree input.rs
+	$(RUSTC) -o $(TMPDIR)/input.hir -Z unpretty=hir-tree input.rs
 	$(CGREP) '"Hello, Rustaceans!\n"' < $(TMPDIR)/input.hir
diff --git a/src/test/run-make/pretty-print-path-suffix/Makefile b/src/test/run-make/pretty-print-path-suffix/Makefile
index d5300501179..899457fc748 100644
--- a/src/test/run-make/pretty-print-path-suffix/Makefile
+++ b/src/test/run-make/pretty-print-path-suffix/Makefile
@@ -1,9 +1,9 @@
 -include ../tools.mk
 
 all:
-	$(RUSTC) -o $(TMPDIR)/foo.out -Z unstable-options --unpretty hir=foo input.rs
-	$(RUSTC) -o $(TMPDIR)/nest_foo.out -Z unstable-options --unpretty hir=nest::foo input.rs
-	$(RUSTC) -o $(TMPDIR)/foo_method.out -Z unstable-options --unpretty hir=foo_method input.rs
+	$(RUSTC) -o $(TMPDIR)/foo.out -Z unpretty=hir=foo input.rs
+	$(RUSTC) -o $(TMPDIR)/nest_foo.out -Z unpretty=hir=nest::foo input.rs
+	$(RUSTC) -o $(TMPDIR)/foo_method.out -Z unpretty=hir=foo_method input.rs
 	diff -u $(TMPDIR)/foo.out foo.pp
 	diff -u $(TMPDIR)/nest_foo.out nest_foo.pp
 	diff -u $(TMPDIR)/foo_method.out foo_method.pp
diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/empty-crate.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/empty-crate.rs
new file mode 100644
index 00000000000..b45d4bf41d6
--- /dev/null
+++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/empty-crate.rs
@@ -0,0 +1,14 @@
+// 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.
+
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![deny(unused_variables)]
diff --git a/src/test/run-pass-fulldeps/proc-macro/empty-crate.rs b/src/test/run-pass-fulldeps/proc-macro/empty-crate.rs
new file mode 100644
index 00000000000..38a2716aee7
--- /dev/null
+++ b/src/test/run-pass-fulldeps/proc-macro/empty-crate.rs
@@ -0,0 +1,17 @@
+// 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.
+
+// aux-build:empty-crate.rs
+// ignore-stage1
+
+#[macro_use]
+extern crate empty_crate;
+
+fn main() {}
diff --git a/src/test/run-pass/dynamic-drop.rs b/src/test/run-pass/dynamic-drop.rs
index 09318e7256f..e2a51bbf14b 100644
--- a/src/test/run-pass/dynamic-drop.rs
+++ b/src/test/run-pass/dynamic-drop.rs
@@ -8,6 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// revisions:lexical nll
+#![cfg_attr(nll, feature(nll))]
+
 // ignore-wasm32-bare compiled with panic=abort by default
 
 #![feature(generators, generator_trait, untagged_unions, slice_patterns, advanced_slice_patterns)]
diff --git a/src/test/rustdoc-js/quoted.js b/src/test/rustdoc-js/quoted.js
new file mode 100644
index 00000000000..dcb85b5de04
--- /dev/null
+++ b/src/test/rustdoc-js/quoted.js
@@ -0,0 +1,23 @@
+// 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.
+
+const QUERY = '"error"';
+
+const EXPECTED = {
+    'others': [
+        { 'path': 'std', 'name': 'error' },
+        { 'path': 'std::fmt', 'name': 'Error' },
+        { 'path': 'std::io', 'name': 'Error' },
+    ],
+    'in_args': [],
+    'returned': [
+        { 'path': 'std::fmt::LowerExp', 'name': 'fmt' },
+    ],
+};
diff --git a/src/test/rustdoc/auto-traits.rs b/src/test/rustdoc/auto-traits.rs
new file mode 100644
index 00000000000..1753c0ebf73
--- /dev/null
+++ b/src/test/rustdoc/auto-traits.rs
@@ -0,0 +1,23 @@
+// 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.
+
+// aux-build:auto-traits.rs
+
+#![feature(optin_builtin_traits)]
+
+#![crate_name = "foo"]
+
+extern crate auto_traits;
+
+// @has 'foo/trait.Foo.html' '//pre' 'pub unsafe auto trait Foo'
+pub unsafe auto trait Foo {}
+
+// @has 'foo/trait.Bar.html' '//pre' 'pub unsafe auto trait Bar'
+pub use auto_traits::Bar;
diff --git a/src/test/rustdoc/auxiliary/auto-traits.rs b/src/test/rustdoc/auxiliary/auto-traits.rs
new file mode 100644
index 00000000000..70299334b46
--- /dev/null
+++ b/src/test/rustdoc/auxiliary/auto-traits.rs
@@ -0,0 +1,13 @@
+// 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.
+
+#![feature(optin_builtin_traits)]
+
+pub unsafe auto trait Bar {}
diff --git a/src/test/ui/issue-29723.rs b/src/test/ui/issue-29723.rs
new file mode 100644
index 00000000000..f31e965ae01
--- /dev/null
+++ b/src/test/ui/issue-29723.rs
@@ -0,0 +1,26 @@
+// 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(nll)]
+
+// test for https://github.com/rust-lang/rust/issues/29723
+
+fn main() {
+    let s = String::new();
+    let _s = match 0 {
+        0 if { drop(s); false } => String::from("oops"),
+        _ => {
+            // This should trigger an error,
+            // s could have been moved from.
+            s
+            //~^ ERROR use of moved value: `s`
+        }
+    };
+}
diff --git a/src/test/ui/issue-29723.stderr b/src/test/ui/issue-29723.stderr
new file mode 100644
index 00000000000..061c3d49323
--- /dev/null
+++ b/src/test/ui/issue-29723.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `s`
+  --> $DIR/issue-29723.rs:22:13
+   |
+18 |         0 if { drop(s); false } => String::from("oops"),
+   |                     - value moved here
+...
+22 |             s
+   |             ^ value used here after move
+   |
+   = note: move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index efbe5e32fcd..bf5fc00428d 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -466,8 +466,7 @@ impl<'test> TestCx<'test> {
         let mut rustc = Command::new(&self.config.rustc_path);
         rustc
             .arg("-")
-            .arg("-Zunstable-options")
-            .args(&["--unpretty", &pretty_type])
+            .args(&["-Z", &format!("unpretty={}", pretty_type)])
             .args(&["--target", &self.config.target])
             .arg("-L")
             .arg(&aux_dir)
diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml
index 4aa096246bc..bc35cbe9fbb 100644
--- a/src/tools/rustbook/Cargo.toml
+++ b/src/tools/rustbook/Cargo.toml
@@ -8,5 +8,5 @@ license = "MIT/Apache-2.0"
 clap = "2.25.0"
 
 [dependencies.mdbook]
-version = "0.0.26"
+version = "0.0.28"
 default-features = false
diff --git a/src/tools/rustbook/src/main.rs b/src/tools/rustbook/src/main.rs
index a0c3e811a7a..50f4364e448 100644
--- a/src/tools/rustbook/src/main.rs
+++ b/src/tools/rustbook/src/main.rs
@@ -52,12 +52,14 @@ fn main() {
 // Build command implementation
 pub fn build(args: &ArgMatches) -> Result<()> {
     let book_dir = get_book_dir(args);
-    let book = MDBook::new(&book_dir).read_config()?;
+    let mut book = MDBook::new(&book_dir).read_config()?;
 
-    let mut book = match args.value_of("dest-dir") {
-        Some(dest_dir) => book.with_destination(dest_dir),
-        None => book,
-    };
+    // Set this to allow us to catch bugs in advance.
+    book.config.build.create_missing = false;
+
+    if let Some(dest_dir) = args.value_of("dest-dir") {
+        book.config.build.build_dir = PathBuf::from(dest_dir);
+    }
 
     book.build()?;