about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-11-15 12:43:01 +0000
committerbors <bors@rust-lang.org>2018-11-15 12:43:01 +0000
commit9649c1f70fddd01843024932df97fb5a2b10bfe8 (patch)
treebc6af666244208eb4354636428ac26731935cbdc /src
parent99e3fca27d141e2d100ebaf5d5a4104234ae201a (diff)
parentd0e08ce88e0926e8e2bc393d3d7982fd767f37b8 (diff)
downloadrust-9649c1f70fddd01843024932df97fb5a2b10bfe8.tar.gz
rust-9649c1f70fddd01843024932df97fb5a2b10bfe8.zip
Auto merge of #55974 - pietroalbini:rollup, r=pietroalbini
Rollup of 17 pull requests

Successful merges:

 - #55182 (Redox: Update to new changes)
 - #55211 (Add BufWriter::buffer method)
 - #55507 (Add link to std::mem::size_of to size_of intrinsic documentation)
 - #55530 (Speed up String::from_utf16)
 - #55556 (Use `Mmap` to open the rmeta file.)
 - #55622 (NetBSD: link libstd with librt in addition to libpthread)
 - #55750 (Make `NodeId` and `HirLocalId` `newtype_index`)
 - #55778 (Wrap some query results in `Lrc`.)
 - #55781 (More precise spans for temps and their drops)
 - #55785 (Add mem::forget_unsized() for forgetting unsized values)
 - #55852 (Rewrite `...` as `..=` as a `MachineApplicable` 2018 idiom lint)
 - #55865 (Unix RwLock: avoid racy access to write_locked)
 - #55901 (fix various typos in doc comments)
 - #55926 (Change sidebar selector to fix compatibility with docs.rs)
 - #55930 (A handful of hir tweaks)
 - #55932 (core/char: Speed up `to_digit()` for `radix <= 10`)
 - #55956 (add tests for some fixed ICEs)

Failed merges:

r? @ghost
Diffstat (limited to 'src')
-rw-r--r--src/Cargo.lock2
-rw-r--r--src/liballoc/collections/btree/node.rs2
-rw-r--r--src/liballoc/raw_vec.rs2
-rw-r--r--src/liballoc/string.rs10
-rw-r--r--src/libcore/benches/char/methods.rs42
-rw-r--r--src/libcore/benches/char/mod.rs11
-rw-r--r--src/libcore/benches/lib.rs1
-rw-r--r--src/libcore/char/methods.rs25
-rw-r--r--src/libcore/intrinsics.rs7
-rw-r--r--src/libcore/lib.rs1
-rw-r--r--src/libcore/mem.rs13
-rw-r--r--src/libcore/num/f32.rs2
-rw-r--r--src/libcore/task/wake.rs2
m---------src/liblibc0
-rw-r--r--src/libproc_macro/lib.rs12
-rw-r--r--src/librustc/dep_graph/cgu_reuse_tracker.rs2
-rw-r--r--src/librustc/dep_graph/dep_node.rs6
-rw-r--r--src/librustc/hir/def.rs2
-rw-r--r--src/librustc/hir/intravisit.rs5
-rw-r--r--src/librustc/hir/lowering.rs4
-rw-r--r--src/librustc/hir/map/hir_id_validator.rs6
-rw-r--r--src/librustc/hir/mod.rs56
-rw-r--r--src/librustc/ich/impls_hir.rs11
-rw-r--r--src/librustc/infer/canonical/canonicalizer.rs2
-rw-r--r--src/librustc/infer/canonical/query_response.rs2
-rw-r--r--src/librustc/infer/canonical/substitute.rs2
-rw-r--r--src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs2
-rw-r--r--src/librustc/infer/higher_ranked/mod.rs2
-rw-r--r--src/librustc/infer/mod.rs6
-rw-r--r--src/librustc/infer/outlives/verify.rs4
-rw-r--r--src/librustc/infer/type_variable.rs2
-rw-r--r--src/librustc/lint/context.rs7
-rw-r--r--src/librustc/lint/levels.rs2
-rw-r--r--src/librustc/lint/mod.rs2
-rw-r--r--src/librustc/session/config.rs12
-rw-r--r--src/librustc/session/mod.rs4
-rw-r--r--src/librustc/traits/object_safety.rs5
-rw-r--r--src/librustc/traits/query/dropck_outlives.rs2
-rw-r--r--src/librustc/traits/specialize/mod.rs2
-rw-r--r--src/librustc/ty/fold.rs4
-rw-r--r--src/librustc/ty/layout.rs2
-rw-r--r--src/librustc/ty/mod.rs8
-rw-r--r--src/librustc/ty/query/mod.rs11
-rw-r--r--src/librustc_codegen_llvm/base.rs2
-rw-r--r--src/librustc_codegen_llvm/intrinsic.rs2
-rw-r--r--src/librustc_codegen_utils/symbol_names.rs2
-rw-r--r--src/librustc_data_structures/graph/scc/mod.rs2
-rw-r--r--src/librustc_data_structures/owning_ref/mod.rs4
-rw-r--r--src/librustc_data_structures/sorted_map.rs2
-rw-r--r--src/librustc_driver/lib.rs4
-rw-r--r--src/librustc_driver/pretty.rs10
-rw-r--r--src/librustc_driver/test.rs10
-rw-r--r--src/librustc_incremental/persist/dirty_clean.rs2
-rw-r--r--src/librustc_lint/builtin.rs58
-rw-r--r--src/librustc_lint/unused.rs4
-rw-r--r--src/librustc_metadata/Cargo.toml4
-rw-r--r--src/librustc_metadata/cstore_impl.rs6
-rw-r--r--src/librustc_metadata/lib.rs2
-rw-r--r--src/librustc_metadata/locator.rs26
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/mod.rs2
-rw-r--r--src/librustc_mir/borrow_check/places_conflict.rs2
-rw-r--r--src/librustc_mir/build/block.rs16
-rw-r--r--src/librustc_mir/build/expr/as_rvalue.rs2
-rw-r--r--src/librustc_mir/build/expr/as_temp.rs16
-rw-r--r--src/librustc_mir/build/expr/into.rs2
-rw-r--r--src/librustc_mir/build/expr/stmt.rs66
-rw-r--r--src/librustc_mir/build/matches/test.rs2
-rw-r--r--src/librustc_mir/build/mod.rs56
-rw-r--r--src/librustc_mir/hair/cx/block.rs3
-rw-r--r--src/librustc_mir/hair/mod.rs6
-rw-r--r--src/librustc_mir/hair/pattern/_match.rs6
-rw-r--r--src/librustc_mir/interpret/validity.rs2
-rw-r--r--src/librustc_passes/rvalue_promotion.rs2
-rw-r--r--src/librustc_resolve/resolve_imports.rs2
-rw-r--r--src/librustc_traits/lowering/mod.rs12
-rw-r--r--src/librustc_typeck/astconv.rs7
-rw-r--r--src/librustc_typeck/check/intrinsic.rs1
-rw-r--r--src/librustc_typeck/check/method/probe.rs2
-rw-r--r--src/librustc_typeck/check/mod.rs6
-rw-r--r--src/librustc_typeck/check/wfcheck.rs4
-rw-r--r--src/librustc_typeck/collect.rs67
-rw-r--r--src/librustc_typeck/outlives/explicit.rs6
-rw-r--r--src/librustdoc/clean/mod.rs2
-rw-r--r--src/librustdoc/clean/simplify.rs4
-rw-r--r--src/librustdoc/config.rs2
-rw-r--r--src/librustdoc/html/static/rustdoc.css2
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs12
-rw-r--r--src/libstd/alloc.rs2
-rw-r--r--src/libstd/build.rs5
-rw-r--r--src/libstd/collections/hash/map.rs2
-rw-r--r--src/libstd/io/buffered.rs48
-rw-r--r--src/libstd/keyword_docs.rs2
-rw-r--r--src/libstd/net/ip.rs2
-rw-r--r--src/libstd/process.rs4
-rw-r--r--src/libstd/sys/redox/fd.rs2
-rw-r--r--src/libstd/sys/redox/mod.rs23
-rw-r--r--src/libstd/sys/redox/os.rs101
-rw-r--r--src/libstd/sys/redox/process.rs115
-rw-r--r--src/libstd/sys/redox/syscall/call.rs17
-rw-r--r--src/libstd/sys/redox/syscall/flag.rs44
-rw-r--r--src/libstd/sys/redox/syscall/number.rs2
-rw-r--r--src/libstd/sys/unix/fd.rs2
-rw-r--r--src/libstd/sys/unix/rwlock.rs6
-rw-r--r--src/libstd/thread/mod.rs2
-rw-r--r--src/libsyntax/ast.rs55
-rw-r--r--src/libsyntax/lib.rs3
-rw-r--r--src/libsyntax/tokenstream.rs2
-rw-r--r--src/libsyntax_ext/deriving/generic/mod.rs2
-rw-r--r--src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs2
-rw-r--r--src/test/ui/issues/issue-54348.rs5
-rw-r--r--src/test/ui/issues/issue-54348.stderr16
-rw-r--r--src/test/ui/issues/issue-55587.rs5
-rw-r--r--src/test/ui/issues/issue-55587.stderr9
-rw-r--r--src/test/ui/lint/inclusive-range-pattern-syntax.fixed6
-rw-r--r--src/test/ui/lint/inclusive-range-pattern-syntax.rs6
-rw-r--r--src/test/ui/lint/inclusive-range-pattern-syntax.stderr6
-rw-r--r--src/test/ui/nll/issue-54382-use-span-of-tail-of-block.nll.stderr20
-rw-r--r--src/test/ui/nll/issue-54382-use-span-of-tail-of-block.rs28
-rw-r--r--src/test/ui/nll/issue-54382-use-span-of-tail-of-block.stderr15
-rw-r--r--src/test/ui/range/range-inclusive-pattern-precedence.stderr4
120 files changed, 933 insertions, 389 deletions
diff --git a/src/Cargo.lock b/src/Cargo.lock
index 0c08e35c18d..64e18899c9d 100644
--- a/src/Cargo.lock
+++ b/src/Cargo.lock
@@ -2278,12 +2278,14 @@ version = "0.0.0"
 dependencies = [
  "flate2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "proc_macro 0.0.0",
  "rustc 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
  "rustc_target 0.0.0",
  "serialize 0.0.0",
+ "stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntax 0.0.0",
  "syntax_ext 0.0.0",
  "syntax_pos 0.0.0",
diff --git a/src/liballoc/collections/btree/node.rs b/src/liballoc/collections/btree/node.rs
index deca9591fbd..f9b455fe796 100644
--- a/src/liballoc/collections/btree/node.rs
+++ b/src/liballoc/collections/btree/node.rs
@@ -69,7 +69,7 @@ struct LeafNode<K, V> {
 
     /// This node's index into the parent node's `edges` array.
     /// `*node.parent.edges[node.parent_idx]` should be the same thing as `node`.
-    /// This is only guaranteed to be initialized when `parent` is nonnull.
+    /// This is only guaranteed to be initialized when `parent` is non-null.
     parent_idx: MaybeUninit<u16>,
 
     /// The number of keys and values this node stores.
diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs
index 837770feece..e87bf78561c 100644
--- a/src/liballoc/raw_vec.rs
+++ b/src/liballoc/raw_vec.rs
@@ -44,7 +44,7 @@ use boxed::Box;
 /// This enables you to use capacity growing logic catch the overflows in your length
 /// that might occur with zero-sized types.
 ///
-/// However this means that you need to be careful when roundtripping this type
+/// However this means that you need to be careful when round-tripping this type
 /// with a `Box<[T]>`: `cap()` won't yield the len. However `with_capacity`,
 /// `shrink_to_fit`, and `from_box` will actually set RawVec's private capacity
 /// field. This allows zero-sized types to not be special-cased by consumers of
diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs
index 2beb3240aac..8d009101ce7 100644
--- a/src/liballoc/string.rs
+++ b/src/liballoc/string.rs
@@ -618,7 +618,15 @@ impl String {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn from_utf16(v: &[u16]) -> Result<String, FromUtf16Error> {
-        decode_utf16(v.iter().cloned()).collect::<Result<_, _>>().map_err(|_| FromUtf16Error(()))
+        let mut ret = String::with_capacity(v.len());
+        for c in decode_utf16(v.iter().cloned()) {
+            if let Ok(c) = c {
+                ret.push(c);
+            } else {
+                return Err(FromUtf16Error(()));
+            }
+        }
+        Ok(ret)
     }
 
     /// Decode a UTF-16 encoded slice `v` into a `String`, replacing
diff --git a/src/libcore/benches/char/methods.rs b/src/libcore/benches/char/methods.rs
new file mode 100644
index 00000000000..faf820d871c
--- /dev/null
+++ b/src/libcore/benches/char/methods.rs
@@ -0,0 +1,42 @@
+// 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.
+
+use test::Bencher;
+
+const CHARS: [char; 9] = ['0', 'x', '2', '5', 'A', 'f', '7', '8', '9'];
+const RADIX: [u32; 5] = [2, 8, 10, 16, 32];
+
+#[bench]
+fn bench_to_digit_radix_2(b: &mut Bencher) {
+    b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_digit(2)).min())
+}
+
+#[bench]
+fn bench_to_digit_radix_10(b: &mut Bencher) {
+    b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_digit(10)).min())
+}
+
+#[bench]
+fn bench_to_digit_radix_16(b: &mut Bencher) {
+    b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_digit(16)).min())
+}
+
+#[bench]
+fn bench_to_digit_radix_36(b: &mut Bencher) {
+    b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_digit(36)).min())
+}
+
+#[bench]
+fn bench_to_digit_radix_var(b: &mut Bencher) {
+    b.iter(|| CHARS.iter().cycle()
+        .zip(RADIX.iter().cycle())
+        .take(10_000)
+        .map(|(c, radix)| c.to_digit(*radix)).min())
+}
diff --git a/src/libcore/benches/char/mod.rs b/src/libcore/benches/char/mod.rs
new file mode 100644
index 00000000000..a656e82cb61
--- /dev/null
+++ b/src/libcore/benches/char/mod.rs
@@ -0,0 +1,11 @@
+// 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.
+
+mod methods;
diff --git a/src/libcore/benches/lib.rs b/src/libcore/benches/lib.rs
index ced77d77918..d44f1577d56 100644
--- a/src/libcore/benches/lib.rs
+++ b/src/libcore/benches/lib.rs
@@ -15,6 +15,7 @@ extern crate core;
 extern crate test;
 
 mod any;
+mod char;
 mod hash;
 mod iter;
 mod num;
diff --git a/src/libcore/char/methods.rs b/src/libcore/char/methods.rs
index 35181afea3d..d6fcff644ac 100644
--- a/src/libcore/char/methods.rs
+++ b/src/libcore/char/methods.rs
@@ -121,15 +121,24 @@ impl char {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn to_digit(self, radix: u32) -> Option<u32> {
-        if radix > 36 {
-            panic!("to_digit: radix is too high (maximum 36)");
-        }
-        let val = match self {
-          '0' ..= '9' => self as u32 - '0' as u32,
-          'a' ..= 'z' => self as u32 - 'a' as u32 + 10,
-          'A' ..= 'Z' => self as u32 - 'A' as u32 + 10,
-          _ => return None,
+        assert!(radix <= 36, "to_digit: radix is too high (maximum 36)");
+
+        // the code is split up here to improve execution speed for cases where
+        // the `radix` is constant and 10 or smaller
+        let val = if radix <= 10  {
+            match self {
+                '0' ..= '9' => self as u32 - '0' as u32,
+                _ => return None,
+            }
+        } else {
+            match self {
+                '0'..='9' => self as u32 - '0' as u32,
+                'a'..='z' => self as u32 - 'a' as u32 + 10,
+                'A'..='Z' => self as u32 - 'A' as u32 + 10,
+                _ => return None,
+            }
         };
+
         if val < radix { Some(val) }
         else { None }
     }
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index 7ed6e4a8f51..16f0299c18b 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -672,6 +672,9 @@ extern "rust-intrinsic" {
     ///
     /// More specifically, this is the offset in bytes between successive
     /// items of the same type, including alignment padding.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::mem::size_of`](../../std/mem/fn.size_of.html).
     pub fn size_of<T>() -> usize;
 
     /// Moves a value to an uninitialized memory location.
@@ -714,6 +717,10 @@ extern "rust-intrinsic" {
     /// initialize memory previous set to the result of `uninit`.
     pub fn uninit<T>() -> T;
 
+    /// Moves a value out of scope without running drop glue.
+    #[cfg(not(stage0))]
+    pub fn forget<T: ?Sized>(_: T);
+
     /// Reinterprets the bits of a value of one type as another type.
     ///
     /// Both types must have the same size. Neither the original, nor the result,
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 5872ac815c2..a02b5bc87c5 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -106,6 +106,7 @@
 #![feature(staged_api)]
 #![feature(stmt_expr_attributes)]
 #![feature(unboxed_closures)]
+#![feature(unsized_locals)]
 #![feature(untagged_unions)]
 #![feature(unwind_attributes)]
 #![feature(doc_alias)]
diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs
index 56146a9a5fd..d8eec2bd9a6 100644
--- a/src/libcore/mem.rs
+++ b/src/libcore/mem.rs
@@ -143,6 +143,19 @@ pub fn forget<T>(t: T) {
     ManuallyDrop::new(t);
 }
 
+/// Like [`forget`], but also accepts unsized values.
+///
+/// This function is just a shim intended to be removed when the `unsized_locals` feature gets
+/// stabilized.
+///
+/// [`forget`]: fn.forget.html
+#[inline]
+#[cfg(not(stage0))]
+#[unstable(feature = "forget_unsized", issue = "0")]
+pub fn forget_unsized<T: ?Sized>(t: T) {
+    unsafe { intrinsics::forget(t) }
+}
+
 /// Returns the size of a type in bytes.
 ///
 /// More specifically, this is the offset in bytes between successive elements
diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs
index 577c823f9a0..d6c3996971a 100644
--- a/src/libcore/num/f32.rs
+++ b/src/libcore/num/f32.rs
@@ -445,7 +445,7 @@ impl f32 {
     /// signaling NaNs on MIPS are quiet NaNs on x86, and vice-versa.
     ///
     /// Rather than trying to preserve signaling-ness cross-platform, this
-    /// implementation favours preserving the exact bits. This means that
+    /// implementation favors preserving the exact bits. This means that
     /// any payloads encoded in NaNs will be preserved even if the result of
     /// this method is sent over the network from an x86 machine to a MIPS one.
     ///
diff --git a/src/libcore/task/wake.rs b/src/libcore/task/wake.rs
index c9fb22e0080..c0ce7255d62 100644
--- a/src/libcore/task/wake.rs
+++ b/src/libcore/task/wake.rs
@@ -108,7 +108,7 @@ impl Drop for Waker {
 /// is ready to be run.
 ///
 /// This is similar to the `Waker` type, but cannot be sent across threads.
-/// Task executors can use this type to implement more optimized singlethreaded wakeup
+/// Task executors can use this type to implement more optimized single-threaded wakeup
 /// behavior.
 #[repr(transparent)]
 #[derive(Clone)]
diff --git a/src/liblibc b/src/liblibc
-Subproject 1844a772b60771d0124a157019f627d60fea4e7
+Subproject c75ca6465a139704e00295be355b1f067af2f53
diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs
index 1a2b16a4fed..60b6a8bac41 100644
--- a/src/libproc_macro/lib.rs
+++ b/src/libproc_macro/lib.rs
@@ -535,7 +535,7 @@ impl TokenTree {
     }
 }
 
-/// Prints token treee in a form convenient for debugging.
+/// Prints token tree in a form convenient for debugging.
 #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
 impl fmt::Debug for TokenTree {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -730,7 +730,7 @@ impl fmt::Debug for Group {
 
 /// An `Punct` is an single punctuation character like `+`, `-` or `#`.
 ///
-/// Multicharacter operators like `+=` are represented as two instances of `Punct` with different
+/// Multi-character operators like `+=` are represented as two instances of `Punct` with different
 /// forms of `Spacing` returned.
 #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
 #[derive(Clone)]
@@ -788,7 +788,7 @@ impl Punct {
 
     /// Returns the spacing of this punctuation character, indicating whether it's immediately
     /// followed by another `Punct` in the token stream, so they can potentially be combined into
-    /// a multicharacter operator (`Joint`), or it's followed by some other token or whitespace
+    /// a multi-character operator (`Joint`), or it's followed by some other token or whitespace
     /// (`Alone`) so the operator has certainly ended.
     #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
     pub fn spacing(&self) -> Spacing {
@@ -947,7 +947,7 @@ macro_rules! suffixed_int_literals {
         /// This function will create an integer like `1u32` where the integer
         /// value specified is the first part of the token and the integral is
         /// also suffixed at the end.
-        /// Literals created from negative numbers may not survive rountrips through
+        /// Literals created from negative numbers may not survive round-trips through
         /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal).
         ///
         /// Literals created through this method have the `Span::call_site()`
@@ -1047,7 +1047,7 @@ impl Literal {
 
     /// Creates a new suffixed floating-point literal.
     ///
-    /// This consturctor will create a literal like `1.0f32` where the value
+    /// This constructor will create a literal like `1.0f32` where the value
     /// specified is the preceding part of the token and `f32` is the suffix of
     /// the token. This token will always be inferred to be an `f32` in the
     /// compiler.
@@ -1096,7 +1096,7 @@ impl Literal {
 
     /// Creates a new suffixed floating-point literal.
     ///
-    /// This consturctor will create a literal like `1.0f64` where the value
+    /// This constructor will create a literal like `1.0f64` where the value
     /// specified is the preceding part of the token and `f64` is the suffix of
     /// the token. This token will always be inferred to be an `f64` in the
     /// compiler.
diff --git a/src/librustc/dep_graph/cgu_reuse_tracker.rs b/src/librustc/dep_graph/cgu_reuse_tracker.rs
index 99fc020bbe4..0392d329896 100644
--- a/src/librustc/dep_graph/cgu_reuse_tracker.rs
+++ b/src/librustc/dep_graph/cgu_reuse_tracker.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 //! Some facilities for tracking how codegen-units are reused during incremental
-//! compilition. This is used for incremental compiliation tests and debug
+//! compilation. This is used for incremental compilation tests and debug
 //! output.
 
 use session::Session;
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index 61996b5a8a7..3ff2545f78d 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -63,7 +63,7 @@
 use mir::interpret::GlobalId;
 use hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX};
 use hir::map::DefPathHash;
-use hir::{HirId, ItemLocalId};
+use hir::HirId;
 
 use ich::{Fingerprint, StableHashingContext};
 use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
@@ -790,11 +790,11 @@ impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for HirId {
     fn to_fingerprint(&self, tcx: TyCtxt<'_, '_, '_>) -> Fingerprint {
         let HirId {
             owner,
-            local_id: ItemLocalId(local_id),
+            local_id,
         } = *self;
 
         let def_path_hash = tcx.def_path_hash(DefId::local(owner));
-        let local_id = Fingerprint::from_smaller_hash(local_id as u64);
+        let local_id = Fingerprint::from_smaller_hash(local_id.as_u32().into());
 
         def_path_hash.0.combine(local_id)
     }
diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs
index 5d9d4deb0ab..e4c434b562d 100644
--- a/src/librustc/hir/def.rs
+++ b/src/librustc/hir/def.rs
@@ -36,7 +36,7 @@ pub enum NonMacroAttrKind {
     Tool,
     /// Single-segment custom attribute registered by a derive macro (`#[serde(default)]`).
     DeriveHelper,
-    /// Single-segment custom attriubte registered by a legacy plugin (`register_attribute`).
+    /// Single-segment custom attribute registered by a legacy plugin (`register_attribute`).
     LegacyPluginHelper,
     /// Single-segment custom attribute not registered in any way (`#[my_attr]`).
     Custom,
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs
index dcc0f8545e5..d9963f23a15 100644
--- a/src/librustc/hir/intravisit.rs
+++ b/src/librustc/hir/intravisit.rs
@@ -49,7 +49,6 @@ use hir::map::{self, Map};
 use super::itemlikevisit::DeepVisitor;
 
 use std::cmp;
-use std::u32;
 
 #[derive(Copy, Clone)]
 pub enum FnKind<'a> {
@@ -1152,8 +1151,8 @@ pub struct IdRange {
 impl IdRange {
     pub fn max() -> IdRange {
         IdRange {
-            min: NodeId::from_u32(u32::MAX),
-            max: NodeId::from_u32(u32::MIN),
+            min: NodeId::MAX,
+            max: NodeId::from_u32(0),
         }
     }
 
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index dd5d4b8f6af..e532b50a28b 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -588,7 +588,7 @@ impl<'a> LoweringContext<'a> {
             *local_id_counter += 1;
             hir::HirId {
                 owner: def_index,
-                local_id: hir::ItemLocalId(local_id),
+                local_id: hir::ItemLocalId::from_u32(local_id),
             }
         })
     }
@@ -616,7 +616,7 @@ impl<'a> LoweringContext<'a> {
 
             hir::HirId {
                 owner: def_index,
-                local_id: hir::ItemLocalId(local_id),
+                local_id: hir::ItemLocalId::from_u32(local_id),
             }
         })
     }
diff --git a/src/librustc/hir/map/hir_id_validator.rs b/src/librustc/hir/map/hir_id_validator.rs
index 896a6163eba..ac4119dc372 100644
--- a/src/librustc/hir/map/hir_id_validator.rs
+++ b/src/librustc/hir/map/hir_id_validator.rs
@@ -101,7 +101,7 @@ impl<'a, 'hir: 'a> HirIdValidator<'a, 'hir> {
         if max != self.hir_ids_seen.len() - 1 {
             // Collect the missing ItemLocalIds
             let missing: Vec<_> = (0 .. max as u32 + 1)
-              .filter(|&i| !self.hir_ids_seen.contains_key(&ItemLocalId(i)))
+              .filter(|&i| !self.hir_ids_seen.contains_key(&ItemLocalId::from_u32(i)))
               .collect();
 
             // Try to map those to something more useful
@@ -110,7 +110,7 @@ impl<'a, 'hir: 'a> HirIdValidator<'a, 'hir> {
             for local_id in missing {
                 let hir_id = HirId {
                     owner: owner_def_index,
-                    local_id: ItemLocalId(local_id as u32),
+                    local_id: ItemLocalId::from_u32(local_id),
                 };
 
                 trace!("missing hir id {:#?}", hir_id);
@@ -124,7 +124,7 @@ impl<'a, 'hir: 'a> HirIdValidator<'a, 'hir> {
                                        .enumerate()
                                        .find(|&(_, &entry)| hir_id == entry)
                                        .expect("no node_to_hir_id entry");
-                let node_id = NodeId::new(node_id);
+                let node_id = NodeId::from_usize(node_id);
                 missing_items.push(format!("[local_id: {}, node:{}]",
                                            local_id,
                                            self.hir_map.node_to_string(node_id)));
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index f57e3ff913b..e28193be34a 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -27,7 +27,7 @@ use syntax_pos::{Span, DUMMY_SP, symbol::InternedString};
 use syntax::source_map::{self, Spanned};
 use rustc_target::spec::abi::Abi;
 use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, DUMMY_NODE_ID, AsmDialect};
-use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, MetaItem};
+use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy};
 use syntax::attr::InlineAttr;
 use syntax::ext::hygiene::SyntaxContext;
 use syntax::ptr::P;
@@ -37,7 +37,6 @@ use syntax::util::parser::ExprPrecedence;
 use ty::AdtKind;
 use ty::query::Providers;
 
-use rustc_data_structures::indexed_vec;
 use rustc_data_structures::sync::{ParallelIterator, par_iter, Send, Sync, scope};
 use rustc_data_structures::thin_vec::ThinVec;
 
@@ -58,7 +57,6 @@ macro_rules! hir_vec {
     ($($x:expr),*) => (
         $crate::hir::HirVec::from(vec![$($x),*])
     );
-    ($($x:expr,)*) => (hir_vec![$($x),*])
 }
 
 pub mod check_attr;
@@ -121,40 +119,28 @@ impl serialize::UseSpecializedDecodable for HirId {
     }
 }
 
-
-/// An `ItemLocalId` uniquely identifies something within a given "item-like",
-/// that is within a hir::Item, hir::TraitItem, or hir::ImplItem. There is no
-/// guarantee that the numerical value of a given `ItemLocalId` corresponds to
-/// the node's position within the owning item in any way, but there is a
-/// guarantee that the `LocalItemId`s within an owner occupy a dense range of
-/// integers starting at zero, so a mapping that maps all or most nodes within
-/// an "item-like" to something else can be implement by a `Vec` instead of a
-/// tree or hash map.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug,
-         RustcEncodable, RustcDecodable)]
-pub struct ItemLocalId(pub u32);
-
-impl ItemLocalId {
-    pub fn as_usize(&self) -> usize {
-        self.0 as usize
+// hack to ensure that we don't try to access the private parts of `ItemLocalId` in this module
+mod item_local_id_inner {
+    use rustc_data_structures::indexed_vec::Idx;
+    /// An `ItemLocalId` uniquely identifies something within a given "item-like",
+    /// that is within a hir::Item, hir::TraitItem, or hir::ImplItem. There is no
+    /// guarantee that the numerical value of a given `ItemLocalId` corresponds to
+    /// the node's position within the owning item in any way, but there is a
+    /// guarantee that the `LocalItemId`s within an owner occupy a dense range of
+    /// integers starting at zero, so a mapping that maps all or most nodes within
+    /// an "item-like" to something else can be implement by a `Vec` instead of a
+    /// tree or hash map.
+    newtype_index! {
+        pub struct ItemLocalId { .. }
     }
 }
 
-impl indexed_vec::Idx for ItemLocalId {
-    fn new(idx: usize) -> Self {
-        debug_assert!((idx as u32) as usize == idx);
-        ItemLocalId(idx as u32)
-    }
-
-    fn index(self) -> usize {
-        self.0 as usize
-    }
-}
+pub use self::item_local_id_inner::ItemLocalId;
 
 /// The `HirId` corresponding to CRATE_NODE_ID and CRATE_DEF_INDEX
 pub const CRATE_HIR_ID: HirId = HirId {
     owner: CRATE_DEF_INDEX,
-    local_id: ItemLocalId(0)
+    local_id: ItemLocalId::from_u32_const(0)
 };
 
 pub const DUMMY_HIR_ID: HirId = HirId {
@@ -162,7 +148,7 @@ pub const DUMMY_HIR_ID: HirId = HirId {
     local_id: DUMMY_ITEM_LOCAL_ID,
 };
 
-pub const DUMMY_ITEM_LOCAL_ID: ItemLocalId = ItemLocalId(!0);
+pub const DUMMY_ITEM_LOCAL_ID: ItemLocalId = ItemLocalId::MAX;
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Copy)]
 pub struct Label {
@@ -331,7 +317,7 @@ impl Path {
 
 impl fmt::Debug for Path {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "path({})", print::to_string(print::NO_ANN, |s| s.print_path(self, false)))
+        write!(f, "path({})", self)
     }
 }
 
@@ -698,8 +684,6 @@ pub struct WhereEqPredicate {
     pub rhs_ty: P<Ty>,
 }
 
-pub type CrateConfig = HirVec<P<MetaItem>>;
-
 /// The top-level data structure that stores the entire contents of
 /// the crate currently being compiled.
 ///
@@ -1196,8 +1180,8 @@ impl StmtKind {
 
     pub fn id(&self) -> NodeId {
         match *self {
-            StmtKind::Decl(_, id) => id,
-            StmtKind::Expr(_, id) => id,
+            StmtKind::Decl(_, id) |
+            StmtKind::Expr(_, id) |
             StmtKind::Semi(_, id) => id,
         }
     }
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index b220634d0d9..ae0d78d2958 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -79,7 +79,14 @@ impl<'a> ToStableHashKey<StableHashingContext<'a>> for CrateNum {
     }
 }
 
-impl_stable_hash_for!(tuple_struct hir::ItemLocalId { index });
+impl<'a> HashStable<StableHashingContext<'a>> for hir::ItemLocalId {
+    #[inline]
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a>,
+                                          hasher: &mut StableHasher<W>) {
+        self.as_u32().hash_stable(hcx, hasher);
+    }
+}
 
 impl<'a> ToStableHashKey<StableHashingContext<'a>>
 for hir::ItemLocalId {
@@ -800,7 +807,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for hir::Mod {
             .iter()
             .map(|id| {
                 let (def_path_hash, local_id) = id.id.to_stable_hash_key(hcx);
-                debug_assert_eq!(local_id, hir::ItemLocalId(0));
+                debug_assert_eq!(local_id, hir::ItemLocalId::from_u32(0));
                 def_path_hash.0
             }).fold(Fingerprint::ZERO, |a, b| {
                 a.combine_commutative(b)
diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs
index 61a861a8a1c..a787eeae663 100644
--- a/src/librustc/infer/canonical/canonicalizer.rs
+++ b/src/librustc/infer/canonical/canonicalizer.rs
@@ -10,7 +10,7 @@
 
 //! This module contains the "canonicalizer" itself.
 //!
-//! For an overview of what canonicaliation is and how it fits into
+//! For an overview of what canonicalization is and how it fits into
 //! rustc, check out the [chapter in the rustc guide][c].
 //!
 //! [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html
diff --git a/src/librustc/infer/canonical/query_response.rs b/src/librustc/infer/canonical/query_response.rs
index f4607f7a909..6f3d1026835 100644
--- a/src/librustc/infer/canonical/query_response.rs
+++ b/src/librustc/infer/canonical/query_response.rs
@@ -556,7 +556,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
     }
 
     /// Given two sets of values for the same set of canonical variables, unify them.
-    /// The second set is produced lazilly by supplying indices from the first set.
+    /// The second set is produced lazily by supplying indices from the first set.
     fn unify_canonical_vars(
         &self,
         cause: &ObligationCause<'tcx>,
diff --git a/src/librustc/infer/canonical/substitute.rs b/src/librustc/infer/canonical/substitute.rs
index 70ce5d0d8dc..e2110e148de 100644
--- a/src/librustc/infer/canonical/substitute.rs
+++ b/src/librustc/infer/canonical/substitute.rs
@@ -11,7 +11,7 @@
 //! This module contains code to substitute new values into a
 //! `Canonical<'tcx, T>`.
 //!
-//! For an overview of what canonicaliation is and how it fits into
+//! For an overview of what canonicalization is and how it fits into
 //! rustc, check out the [chapter in the rustc guide][c].
 //!
 //! [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html
diff --git a/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs b/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs
index 009a8235681..7a92b3084ba 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs
@@ -20,7 +20,7 @@ use util::common::ErrorReported;
 use infer::lexical_region_resolve::RegionResolutionError::SubSupConflict;
 
 impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
-    /// Print the error message for lifetime errors when binding excapes a closure.
+    /// Print the error message for lifetime errors when binding escapes a closure.
     ///
     /// Consider a case where we have
     ///
diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs
index 642382bcf0f..8172f620c36 100644
--- a/src/librustc/infer/higher_ranked/mod.rs
+++ b/src/librustc/infer/higher_ranked/mod.rs
@@ -428,7 +428,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     ///
     /// This routine is only intended to be used when the leak-check has
     /// passed; currently, it's used in the trait matching code to create
-    /// a set of nested obligations frmo an impl that matches against
+    /// a set of nested obligations from an impl that matches against
     /// something higher-ranked.  More details can be found in
     /// `librustc/middle/traits/README.md`.
     ///
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index 4ddf47c88dd..87e32be1a17 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -1160,10 +1160,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     }
 
     /// Takes ownership of the list of variable regions. This implies
-    /// that all the region constriants have already been taken, and
+    /// that all the region constraints have already been taken, and
     /// hence that `resolve_regions_and_report_errors` can never be
     /// called. This is used only during NLL processing to "hand off" ownership
-    /// of the set of region vairables into the NLL region context.
+    /// of the set of region variables into the NLL region context.
     pub fn take_region_var_origins(&self) -> VarInfos {
         let (var_infos, data) = self.region_constraints
             .borrow_mut()
@@ -1478,7 +1478,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     }
 
     /// Clears the selection, evaluation, and projection caches. This is useful when
-    /// repeatedly attemping to select an Obligation while changing only
+    /// repeatedly attempting to select an Obligation while changing only
     /// its ParamEnv, since FulfillmentContext doesn't use 'probe'
     pub fn clear_caches(&self) {
         self.selection_cache.clear();
diff --git a/src/librustc/infer/outlives/verify.rs b/src/librustc/infer/outlives/verify.rs
index a7a79dd2e65..5fee04341b6 100644
--- a/src/librustc/infer/outlives/verify.rs
+++ b/src/librustc/infer/outlives/verify.rs
@@ -299,8 +299,8 @@ impl<'cx, 'gcx, 'tcx> VerifyBoundCx<'cx, 'gcx, 'tcx> {
         let assoc_item = tcx.associated_item(assoc_item_def_id);
         let trait_def_id = assoc_item.container.assert_trait();
         let trait_predicates = tcx.predicates_of(trait_def_id).predicates
-            .into_iter()
-            .map(|(p, _)| p)
+            .iter()
+            .map(|(p, _)| *p)
             .collect();
         let identity_substs = Substs::identity_for_item(tcx, assoc_item_def_id);
         let identity_proj = tcx.mk_projection(assoc_item_def_id, identity_substs);
diff --git a/src/librustc/infer/type_variable.rs b/src/librustc/infer/type_variable.rs
index 39bf59a7a4e..bec19ba9099 100644
--- a/src/librustc/infer/type_variable.rs
+++ b/src/librustc/infer/type_variable.rs
@@ -320,7 +320,7 @@ impl<'tcx> TypeVariableTable<'tcx> {
     /// but which have only been unified since `s` started, and
     /// return the types with which they were unified. So if we had
     /// a type variable `V0`, then we started the snapshot, then we
-    /// created a type variable `V1`, unifed `V0` with `T0`, and
+    /// created a type variable `V1`, unified `V0` with `T0`, and
     /// unified `V1` with `T1`, this function would return `{T0}`.
     pub fn types_escaping_snapshot(&mut self, s: &Snapshot<'tcx>) -> Vec<Ty<'tcx>> {
         let mut new_elem_threshold = u32::MAX;
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index 5470aff77f8..8acbaaa844d 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -1020,9 +1020,12 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> {
     }
 
     fn visit_pat(&mut self, p: &'a ast::Pat) {
-        run_lints!(self, check_pat, p);
+        let mut visit_subpats = true;
+        run_lints!(self, check_pat, p, &mut visit_subpats);
         self.check_id(p.id);
-        ast_visit::walk_pat(self, p);
+        if visit_subpats {
+            ast_visit::walk_pat(self, p);
+        }
     }
 
     fn visit_expr(&mut self, e: &'a ast::Expr) {
diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs
index 732b32cc35d..cfb9f04c4c6 100644
--- a/src/librustc/lint/levels.rs
+++ b/src/librustc/lint/levels.rs
@@ -189,7 +189,7 @@ impl<'a> LintLevelsBuilder<'a> {
     /// This function will perform a number of tasks:
     ///
     /// * It'll validate all lint-related attributes in `attrs`
-    /// * It'll mark all lint-related attriutes as used
+    /// * It'll mark all lint-related attributes as used
     /// * Lint levels will be updated based on the attributes provided
     /// * Lint attributes are validated, e.g. a #[forbid] can't be switched to
     ///   #[allow]
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index afd78008109..18922ec5d17 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -341,7 +341,7 @@ pub trait EarlyLintPass: LintPass {
     fn check_block_post(&mut self, _: &EarlyContext<'_>, _: &ast::Block) { }
     fn check_stmt(&mut self, _: &EarlyContext<'_>, _: &ast::Stmt) { }
     fn check_arm(&mut self, _: &EarlyContext<'_>, _: &ast::Arm) { }
-    fn check_pat(&mut self, _: &EarlyContext<'_>, _: &ast::Pat) { }
+    fn check_pat(&mut self, _: &EarlyContext<'_>, _: &ast::Pat, _: &mut bool) { }
     fn check_expr(&mut self, _: &EarlyContext<'_>, _: &ast::Expr) { }
     fn check_expr_post(&mut self, _: &EarlyContext<'_>, _: &ast::Expr) { }
     fn check_ty(&mut self, _: &EarlyContext<'_>, _: &ast::Ty) { }
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 78aabf86e30..ee6d970750a 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -224,7 +224,7 @@ impl Default for ErrorOutputType {
 
 // Use tree-based collections to cheaply get a deterministic Hash implementation.
 // DO NOT switch BTreeMap out for an unsorted container type! That would break
-// dependency tracking for commandline arguments.
+// dependency tracking for command-line arguments.
 #[derive(Clone, Hash)]
 pub struct OutputTypes(BTreeMap<OutputType, Option<PathBuf>>);
 
@@ -273,7 +273,7 @@ impl OutputTypes {
 
 // Use tree-based collections to cheaply get a deterministic Hash implementation.
 // DO NOT switch BTreeMap or BTreeSet out for an unsorted container type! That
-// would break dependency tracking for commandline arguments.
+// would break dependency tracking for command-line arguments.
 #[derive(Clone, Hash)]
 pub struct Externs(BTreeMap<String, BTreeSet<Option<String>>>);
 
@@ -339,7 +339,7 @@ macro_rules! top_level_options {
     );
 }
 
-// The top-level commandline options struct
+// The top-level command-line options struct
 //
 // For each option, one has to specify how it behaves with regard to the
 // dependency tracking system of incremental compilation. This is done via the
@@ -2377,11 +2377,11 @@ impl fmt::Display for CrateType {
     }
 }
 
-/// Commandline arguments passed to the compiler have to be incorporated with
+/// Command-line arguments passed to the compiler have to be incorporated with
 /// the dependency tracking system for incremental compilation. This module
 /// provides some utilities to make this more convenient.
 ///
-/// The values of all commandline arguments that are relevant for dependency
+/// The values of all command-line arguments that are relevant for dependency
 /// tracking are hashed into a single value that determines whether the
 /// incremental compilation cache can be re-used or not. This hashing is done
 /// via the DepTrackingHash trait defined below, since the standard Hash
@@ -2394,7 +2394,7 @@ impl fmt::Display for CrateType {
 /// impl_dep_tracking_hash_via_hash!() macro that allows to simply reuse the
 /// Hash implementation for DepTrackingHash. It's important though that
 /// we have an opt-in scheme here, so one is hopefully forced to think about
-/// how the hash should be calculated when adding a new commandline argument.
+/// how the hash should be calculated when adding a new command-line argument.
 mod dep_tracking {
     use lint;
     use middle::cstore;
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index 8cfbd27fc61..8582900b72c 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -393,7 +393,7 @@ impl Session {
 
         match id.as_usize().checked_add(count) {
             Some(next) => {
-                self.next_node_id.set(ast::NodeId::new(next));
+                self.next_node_id.set(ast::NodeId::from_usize(next));
             }
             None => bug!("Input too large, ran out of node ids!"),
         }
@@ -1160,7 +1160,7 @@ pub fn build_session_(
         recursion_limit: Once::new(),
         type_length_limit: Once::new(),
         const_eval_stack_frame_limit: 100,
-        next_node_id: OneThread::new(Cell::new(NodeId::new(1))),
+        next_node_id: OneThread::new(Cell::new(NodeId::from_u32(1))),
         allocator_kind: Once::new(),
         injected_panic_runtime: Once::new(),
         imported_macro_spans: OneThread::new(RefCell::new(FxHashMap::default())),
diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs
index 1d76ccdca31..715ce0d7e80 100644
--- a/src/librustc/traits/object_safety.rs
+++ b/src/librustc/traits/object_safety.rs
@@ -182,7 +182,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
         };
         predicates
             .predicates
-            .into_iter()
+            .iter()
             .map(|(predicate, _)| predicate.subst_supertrait(self, &trait_ref))
             .any(|predicate| {
                 match predicate {
@@ -302,9 +302,10 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
             return Some(MethodViolationCode::Generic);
         }
 
-        if self.predicates_of(method.def_id).predicates.into_iter()
+        if self.predicates_of(method.def_id).predicates.iter()
                 // A trait object can't claim to live more than the concrete type,
                 // so outlives predicates will always hold.
+                .cloned()
                 .filter(|(p, _)| p.to_opt_type_outlives().is_none())
                 .collect::<Vec<_>>()
                 // Do a shallow visit so that `contains_illegal_self_type_reference`
diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs
index 62317f07476..99dc099d577 100644
--- a/src/librustc/traits/query/dropck_outlives.rs
+++ b/src/librustc/traits/query/dropck_outlives.rs
@@ -200,7 +200,7 @@ impl_stable_hash_for!(struct DtorckConstraint<'tcx> {
 /// trivial for dropck-outlives.
 ///
 /// Note also that `needs_drop` requires a "global" type (i.e., one
-/// with erased regions), but this funtcion does not.
+/// with erased regions), but this function does not.
 pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) -> bool {
     match ty.sty {
         // None of these types have a destructor and hence they do not
diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs
index d7b5dd049e3..d3dc1655b0d 100644
--- a/src/librustc/traits/specialize/mod.rs
+++ b/src/librustc/traits/specialize/mod.rs
@@ -407,7 +407,7 @@ fn to_pretty_impl_header(tcx: TyCtxt<'_, '_, '_>, impl_def_id: DefId) -> Option<
 
     // The predicates will contain default bounds like `T: Sized`. We need to
     // remove these bounds, and add `T: ?Sized` to any untouched type parameters.
-    let predicates = tcx.predicates_of(impl_def_id).predicates;
+    let predicates = &tcx.predicates_of(impl_def_id).predicates;
     let mut pretty_predicates = Vec::with_capacity(
         predicates.len() + types_without_default_bounds.len());
 
diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs
index a897afa0ca6..2c781483145 100644
--- a/src/librustc/ty/fold.rs
+++ b/src/librustc/ty/fold.rs
@@ -781,7 +781,7 @@ pub fn shift_vars<'a, 'gcx, 'tcx, T>(
 ///
 /// Note that what I'm calling an "escaping var" is often just called a "free var". However,
 /// we already use the term "free var". It refers to the regions or types that we use to represent
-/// bound regions or type params on a fn definition while we are typechecking its body.
+/// bound regions or type params on a fn definition while we are type checking its body.
 ///
 /// To clarify, conceptually there is no particular difference between
 /// an "escaping" var and a "free" var. However, there is a big
@@ -857,7 +857,7 @@ struct LateBoundRegionsCollector {
 
     /// If true, we only want regions that are known to be
     /// "constrained" when you equate this type with another type. In
-    /// partcular, if you have e.g. `&'a u32` and `&'b u32`, equating
+    /// particular, if you have e.g. `&'a u32` and `&'b u32`, equating
     /// them constraints `'a == 'b`.  But if you have `<&'a u32 as
     /// Trait>::Foo` and `<&'b u32 as Trait>::Foo`, normalizing those
     /// types may mean that `'a` and `'b` don't appear in the results,
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index 877bd5a82e6..79324bd97a3 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -1287,7 +1287,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
 /// Type size "skeleton", i.e. the only information determining a type's size.
 /// While this is conservative, (aside from constant sizes, only pointers,
 /// newtypes thereof and null pointer optimized enums are allowed), it is
-/// enough to statically check common usecases of transmute.
+/// enough to statically check common use cases of transmute.
 #[derive(Copy, Clone, Debug)]
 pub enum SizeSkeleton<'tcx> {
     /// Any statically computable Layout.
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 8197136d189..96f4b1ef8e3 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -2130,7 +2130,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
     }
 
     #[inline]
-    pub fn predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> GenericPredicates<'gcx> {
+    pub fn predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Lrc<GenericPredicates<'gcx>> {
         tcx.predicates_of(self.did)
     }
 
@@ -2373,8 +2373,8 @@ impl<'a, 'gcx, 'tcx> AdtDef {
                     def_id: sized_trait,
                     substs: tcx.mk_substs_trait(ty, &[])
                 }).to_predicate();
-                let predicates = tcx.predicates_of(self.did).predicates;
-                if predicates.into_iter().any(|(p, _)| p == sized_predicate) {
+                let predicates = &tcx.predicates_of(self.did).predicates;
+                if predicates.iter().any(|(p, _)| *p == sized_predicate) {
                     vec![]
                 } else {
                     vec![ty]
@@ -2400,7 +2400,7 @@ impl<'a, 'gcx, 'tcx> FieldDef {
 
 /// Represents the various closure traits in the Rust language. This
 /// will determine the type of the environment (`self`, in the
-/// desuaring) argument that the closure expects.
+/// desugaring) argument that the closure expects.
 ///
 /// You can get the environment type of a closure using
 /// `tcx.closure_env_ty()`.
diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs
index c82a44011db..89e7f4db502 100644
--- a/src/librustc/ty/query/mod.rs
+++ b/src/librustc/ty/query/mod.rs
@@ -127,17 +127,18 @@ define_queries! { <'tcx>
         /// predicate gets in the way of some checks, which are intended
         /// to operate over only the actual where-clauses written by the
         /// user.)
-        [] fn predicates_of: PredicatesOfItem(DefId) -> ty::GenericPredicates<'tcx>,
+        [] fn predicates_of: PredicatesOfItem(DefId) -> Lrc<ty::GenericPredicates<'tcx>>,
 
         /// Maps from the def-id of an item (trait/struct/enum/fn) to the
         /// predicates (where clauses) directly defined on it. This is
         /// equal to the `explicit_predicates_of` predicates plus the
         /// `inferred_outlives_of` predicates.
-        [] fn predicates_defined_on: PredicatesDefinedOnItem(DefId) -> ty::GenericPredicates<'tcx>,
+        [] fn predicates_defined_on: PredicatesDefinedOnItem(DefId)
+            -> Lrc<ty::GenericPredicates<'tcx>>,
 
         /// Returns the predicates written explicit by the user.
         [] fn explicit_predicates_of: ExplicitPredicatesOfItem(DefId)
-            -> ty::GenericPredicates<'tcx>,
+            -> Lrc<ty::GenericPredicates<'tcx>>,
 
         /// Returns the inferred outlives predicates (e.g., for `struct
         /// Foo<'a, T> { x: &'a T }`, this would return `T: 'a`).
@@ -149,12 +150,12 @@ define_queries! { <'tcx>
         /// evaluate them even during type conversion, often before the
         /// full predicates are available (note that supertraits have
         /// additional acyclicity requirements).
-        [] fn super_predicates_of: SuperPredicatesOfItem(DefId) -> ty::GenericPredicates<'tcx>,
+        [] fn super_predicates_of: SuperPredicatesOfItem(DefId) -> Lrc<ty::GenericPredicates<'tcx>>,
 
         /// To avoid cycles within the predicates of a single item we compute
         /// per-type-parameter predicates for resolving `T::AssocTy`.
         [] fn type_param_predicates: type_param_predicates((DefId, DefId))
-            -> ty::GenericPredicates<'tcx>,
+            -> Lrc<ty::GenericPredicates<'tcx>>,
 
         [] fn trait_def: TraitDefOfItem(DefId) -> &'tcx ty::TraitDef,
         [] fn adt_def: AdtDefOfItem(DefId) -> &'tcx ty::AdtDef,
diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs
index 821b074cd68..9971a415603 100644
--- a/src/librustc_codegen_llvm/base.rs
+++ b/src/librustc_codegen_llvm/base.rs
@@ -942,7 +942,7 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 ///
 /// In the process of working on rust-lang/rust#55238 a mysterious segfault was
 /// stumbled upon. The segfault was never reproduced locally, but it was
-/// suspected to be releated to the fact that codegen worker threads were
+/// suspected to be related to the fact that codegen worker threads were
 /// sticking around by the time the main thread was exiting, causing issues.
 ///
 /// This structure is an attempt to fix that issue where the `codegen_aborted`
diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs
index a5f90149f4a..8f79d49b3e2 100644
--- a/src/librustc_codegen_llvm/intrinsic.rs
+++ b/src/librustc_codegen_llvm/intrinsic.rs
@@ -194,7 +194,7 @@ pub fn codegen_intrinsic_call(
             return;
         }
         // Effectively no-ops
-        "uninit" => {
+        "uninit" | "forget" => {
             return;
         }
         "needs_drop" => {
diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs
index 0d95b0c7bbc..f8593363bb1 100644
--- a/src/librustc_codegen_utils/symbol_names.rs
+++ b/src/librustc_codegen_utils/symbol_names.rs
@@ -79,7 +79,7 @@
 //! - In order to be able to also use symbols from two versions of the same
 //!   crate (which naturally also have the same name), a stronger measure is
 //!   required: The compiler accepts an arbitrary "disambiguator" value via the
-//!   `-C metadata` commandline argument. This disambiguator is then fed into
+//!   `-C metadata` command-line argument. This disambiguator is then fed into
 //!   the symbol hash of every exported item. Consequently, the symbols in two
 //!   identical crates but with different disambiguators are not in conflict
 //!   with each other. This facility is mainly intended to be used by build
diff --git a/src/librustc_data_structures/graph/scc/mod.rs b/src/librustc_data_structures/graph/scc/mod.rs
index a989a540102..64de0c2f565 100644
--- a/src/librustc_data_structures/graph/scc/mod.rs
+++ b/src/librustc_data_structures/graph/scc/mod.rs
@@ -38,7 +38,7 @@ struct SccData<S: Idx> {
     /// successors can be found.
     ranges: IndexVec<S, Range<usize>>,
 
-    /// Contains the succcessors for all the Sccs, concatenated. The
+    /// Contains the successors for all the Sccs, concatenated. The
     /// range of indices corresponding to a given SCC is found in its
     /// SccData.
     all_successors: Vec<S>,
diff --git a/src/librustc_data_structures/owning_ref/mod.rs b/src/librustc_data_structures/owning_ref/mod.rs
index 02640a71010..27c2f8b718a 100644
--- a/src/librustc_data_structures/owning_ref/mod.rs
+++ b/src/librustc_data_structures/owning_ref/mod.rs
@@ -452,7 +452,7 @@ impl<O, T: ?Sized> OwningRef<O, T> {
     /// use owning_ref::{OwningRef, Erased};
     ///
     /// fn main() {
-    ///     // NB: Using the concrete types here for explicitnes.
+    ///     // NB: Using the concrete types here for explicitness.
     ///     // For less verbose code type aliases like `BoxRef` are provided.
     ///
     ///     let owning_ref_a: OwningRef<Box<[i32; 4]>, [i32; 4]>
@@ -722,7 +722,7 @@ impl<O, T: ?Sized> OwningRefMut<O, T> {
     /// use owning_ref::{OwningRefMut, Erased};
     ///
     /// fn main() {
-    ///     // NB: Using the concrete types here for explicitnes.
+    ///     // NB: Using the concrete types here for explicitness.
     ///     // For less verbose code type aliases like `BoxRef` are provided.
     ///
     ///     let owning_ref_mut_a: OwningRefMut<Box<[i32; 4]>, [i32; 4]>
diff --git a/src/librustc_data_structures/sorted_map.rs b/src/librustc_data_structures/sorted_map.rs
index 730b13a0584..29d99a6aef3 100644
--- a/src/librustc_data_structures/sorted_map.rs
+++ b/src/librustc_data_structures/sorted_map.rs
@@ -15,7 +15,7 @@ use std::mem;
 use std::ops::{RangeBounds, Bound, Index, IndexMut};
 
 /// `SortedMap` is a data structure with similar characteristics as BTreeMap but
-/// slightly different trade-offs: lookup, inseration, and removal are O(log(N))
+/// slightly different trade-offs: lookup, insertion, and removal are O(log(N))
 /// and elements can be iterated in order cheaply.
 ///
 /// `SortedMap` can be faster than a `BTreeMap` for small sizes (<50) since it
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 6c7982242bf..ec3cb95db88 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -643,8 +643,8 @@ impl Compilation {
     }
 }
 
-/// A trait for customising the compilation process. Offers a number of hooks for
-/// executing custom code or customising input.
+/// A trait for customizing the compilation process. Offers a number of hooks for
+/// executing custom code or customizing input.
 pub trait CompilerCalls<'a> {
     /// Hook for a callback early in the process of handling arguments. This will
     /// be called straight after options have been parsed but before anything
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index b4f6d10b1f8..c7ba31e3395 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -425,7 +425,7 @@ impl<'hir> pprust_hir::PpAnn for IdentifiedAnnotation<'hir> {
             pprust_hir::AnnNode::Item(item) => {
                 s.s.space()?;
                 s.synth_comment(format!("node_id: {} hir local_id: {}",
-                                        item.id, item.hir_id.local_id.0))
+                                        item.id, item.hir_id.local_id.as_u32()))
             }
             pprust_hir::AnnNode::SubItem(id) => {
                 s.s.space()?;
@@ -434,18 +434,18 @@ impl<'hir> pprust_hir::PpAnn for IdentifiedAnnotation<'hir> {
             pprust_hir::AnnNode::Block(blk) => {
                 s.s.space()?;
                 s.synth_comment(format!("block node_id: {} hir local_id: {}",
-                                        blk.id, blk.hir_id.local_id.0))
+                                        blk.id, blk.hir_id.local_id.as_u32()))
             }
             pprust_hir::AnnNode::Expr(expr) => {
                 s.s.space()?;
                 s.synth_comment(format!("node_id: {} hir local_id: {}",
-                                        expr.id, expr.hir_id.local_id.0))?;
+                                        expr.id, expr.hir_id.local_id.as_u32()))?;
                 s.pclose()
             }
             pprust_hir::AnnNode::Pat(pat) => {
                 s.s.space()?;
                 s.synth_comment(format!("pat node_id: {} hir local_id: {}",
-                                        pat.id, pat.hir_id.local_id.0))
+                                        pat.id, pat.hir_id.local_id.as_u32()))
             }
         }
     }
@@ -566,7 +566,7 @@ impl FromStr for UserIdentifiedItem {
     type Err = ();
     fn from_str(s: &str) -> Result<UserIdentifiedItem, ()> {
         Ok(s.parse()
-            .map(ast::NodeId::new)
+            .map(ast::NodeId::from_u32)
             .map(ItemViaNode)
             .unwrap_or_else(|_| ItemViaPath(s.split("::").map(|s| s.to_string()).collect())))
     }
diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs
index 28b7c610a91..8865c7e438e 100644
--- a/src/librustc_driver/test.rs
+++ b/src/librustc_driver/test.rs
@@ -232,20 +232,20 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> {
         // children of 1, etc
 
         let dscope = region::Scope {
-            id: hir::ItemLocalId(1),
+            id: hir::ItemLocalId::from_u32(1),
             data: region::ScopeData::Destruction,
         };
         self.region_scope_tree.record_scope_parent(dscope, None);
         self.create_region_hierarchy(
             &RH {
-                id: hir::ItemLocalId(1),
+                id: hir::ItemLocalId::from_u32(1),
                 sub: &[
                     RH {
-                        id: hir::ItemLocalId(10),
+                        id: hir::ItemLocalId::from_u32(10),
                         sub: &[],
                     },
                     RH {
-                        id: hir::ItemLocalId(11),
+                        id: hir::ItemLocalId::from_u32(11),
                         sub: &[],
                     },
                 ],
@@ -400,7 +400,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> {
 
     pub fn t_rptr_scope(&self, id: u32) -> Ty<'tcx> {
         let r = ty::ReScope(region::Scope {
-            id: hir::ItemLocalId(id),
+            id: hir::ItemLocalId::from_u32(id),
             data: region::ScopeData::Node,
         });
         self.infcx
diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs
index 58a799bb45f..f76086139ed 100644
--- a/src/librustc_incremental/persist/dirty_clean.rs
+++ b/src/librustc_incremental/persist/dirty_clean.rs
@@ -160,7 +160,7 @@ const LABELS_FN_IN_TRAIT: &[&[&str]] = &[
     EXTRA_TRAIT,
 ];
 
-/// For generic cases like inline-assemply/mod/etc
+/// For generic cases like inline-assembly/mod/etc
 const LABELS_HIR_ONLY: &[&[&str]] = &[
     BASE_HIR,
 ];
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 2a9b58200e5..bef7b364d84 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -40,6 +40,8 @@ use rustc::util::nodemap::FxHashSet;
 
 use syntax::tokenstream::{TokenTree, TokenStream};
 use syntax::ast;
+use syntax::ptr::P;
+use syntax::ast::Expr;
 use syntax::attr;
 use syntax::source_map::Spanned;
 use syntax::edition::Edition;
@@ -47,6 +49,7 @@ use syntax::feature_gate::{AttributeGate, AttributeType, Stability, deprecated_a
 use syntax_pos::{BytePos, Span, SyntaxContext};
 use syntax::symbol::keywords;
 use syntax::errors::{Applicability, DiagnosticBuilder};
+use syntax::print::pprust::expr_to_string;
 
 use rustc::hir::{self, GenericParamKind, PatKind};
 use rustc::hir::intravisit::FnKind;
@@ -1407,21 +1410,48 @@ impl LintPass for EllipsisInclusiveRangePatterns {
 }
 
 impl EarlyLintPass for EllipsisInclusiveRangePatterns {
-    fn check_pat(&mut self, cx: &EarlyContext, pat: &ast::Pat) {
-        use self::ast::{PatKind, RangeEnd, RangeSyntax};
+    fn check_pat(&mut self, cx: &EarlyContext, pat: &ast::Pat, visit_subpats: &mut bool) {
+        use self::ast::{PatKind, RangeEnd, RangeSyntax::DotDotDot};
+
+        /// If `pat` is a `...` pattern, return the start and end of the range, as well as the span
+        /// corresponding to the ellipsis.
+        fn matches_ellipsis_pat(pat: &ast::Pat) -> Option<(&P<Expr>, &P<Expr>, Span)> {
+            match &pat.node {
+                PatKind::Range(a, b, Spanned { span, node: RangeEnd::Included(DotDotDot), .. }) => {
+                    Some((a, b, *span))
+                }
+                _ => None,
+            }
+        }
 
-        if let PatKind::Range(
-            _, _, Spanned { span, node: RangeEnd::Included(RangeSyntax::DotDotDot) }
-        ) = pat.node {
+        let (parenthesise, endpoints) = match &pat.node {
+            PatKind::Ref(subpat, _) => (true, matches_ellipsis_pat(&subpat)),
+            _ => (false, matches_ellipsis_pat(pat)),
+        };
+
+        if let Some((start, end, join)) = endpoints {
             let msg = "`...` range patterns are deprecated";
-            let mut err = cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, span, msg);
-            err.span_suggestion_short_with_applicability(
-                span, "use `..=` for an inclusive range", "..=".to_owned(),
-                // FIXME: outstanding problem with precedence in ref patterns:
-                // https://github.com/rust-lang/rust/issues/51043#issuecomment-392252285
-                Applicability::MaybeIncorrect
-            );
-            err.emit()
+            let suggestion = "use `..=` for an inclusive range";
+            if parenthesise {
+                *visit_subpats = false;
+                let mut err = cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, pat.span, msg);
+                err.span_suggestion_with_applicability(
+                    pat.span,
+                    suggestion,
+                    format!("&({}..={})", expr_to_string(&start), expr_to_string(&end)),
+                    Applicability::MachineApplicable,
+                );
+                err.emit();
+            } else {
+                let mut err = cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, join, msg);
+                err.span_suggestion_short_with_applicability(
+                    join,
+                    suggestion,
+                    "..=".to_owned(),
+                    Applicability::MachineApplicable,
+                );
+                err.emit();
+            };
         }
     }
 }
@@ -1486,7 +1516,7 @@ declare_lint! {
     "detects edition keywords being used as an identifier"
 }
 
-/// Checks for uses of edtion keywords used as an identifier
+/// Checks for uses of edition keywords used as an identifier
 #[derive(Clone)]
 pub struct KeywordIdents;
 
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index 6d365e6d1ec..7eab7d21002 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -396,12 +396,12 @@ impl EarlyLintPass for UnusedParens {
         self.check_unused_parens_expr(cx, &value, msg, followed_by_block);
     }
 
-    fn check_pat(&mut self, cx: &EarlyContext, p: &ast::Pat) {
+    fn check_pat(&mut self, cx: &EarlyContext, p: &ast::Pat, _: &mut bool) {
         use ast::PatKind::{Paren, Range};
         // The lint visitor will visit each subpattern of `p`. We do not want to lint any range
         // pattern no matter where it occurs in the pattern. For something like `&(a..=b)`, there
         // is a recursive `check_pat` on `a` and `b`, but we will assume that if there are
-        // unnecessry parens they serve a purpose of readability.
+        // unnecessary parens they serve a purpose of readability.
         if let Paren(ref pat) = p.node {
             match pat.node {
                 Range(..) => {}
diff --git a/src/librustc_metadata/Cargo.toml b/src/librustc_metadata/Cargo.toml
index 338824d5efe..276e2a911e6 100644
--- a/src/librustc_metadata/Cargo.toml
+++ b/src/librustc_metadata/Cargo.toml
@@ -11,12 +11,14 @@ crate-type = ["dylib"]
 [dependencies]
 flate2 = "1.0"
 log = "0.4"
+memmap = "0.6"
 proc_macro = { path = "../libproc_macro" }
 rustc = { path = "../librustc" }
-rustc_target = { path = "../librustc_target" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
+rustc_target = { path = "../librustc_target" }
 serialize = { path = "../libserialize" }
+stable_deref_trait = "1.0.0"
 syntax = { path = "../libsyntax" }
 syntax_ext = { path = "../libsyntax_ext" }
 syntax_pos = { path = "../libsyntax_pos" }
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index e6e1367b592..e1d9ca5339e 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -103,9 +103,9 @@ provide! { <'tcx> tcx, def_id, other, cdata,
     generics_of => {
         tcx.alloc_generics(cdata.get_generics(def_id.index, tcx.sess))
     }
-    predicates_of => { cdata.get_predicates(def_id.index, tcx) }
-    predicates_defined_on => { cdata.get_predicates_defined_on(def_id.index, tcx) }
-    super_predicates_of => { cdata.get_super_predicates(def_id.index, tcx) }
+    predicates_of => { Lrc::new(cdata.get_predicates(def_id.index, tcx)) }
+    predicates_defined_on => { Lrc::new(cdata.get_predicates_defined_on(def_id.index, tcx)) }
+    super_predicates_of => { Lrc::new(cdata.get_super_predicates(def_id.index, tcx)) }
     trait_def => {
         tcx.alloc_trait_def(cdata.get_trait_def(def_id.index, tcx.sess))
     }
diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs
index 0cc0707a3a5..0322c888ad5 100644
--- a/src/librustc_metadata/lib.rs
+++ b/src/librustc_metadata/lib.rs
@@ -30,6 +30,8 @@
 extern crate libc;
 #[macro_use]
 extern crate log;
+extern crate memmap;
+extern crate stable_deref_trait;
 #[macro_use]
 extern crate syntax;
 extern crate syntax_pos;
diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs
index a732446d504..528c96f240d 100644
--- a/src/librustc_metadata/locator.rs
+++ b/src/librustc_metadata/locator.rs
@@ -243,12 +243,14 @@ use std::cmp;
 use std::fmt;
 use std::fs;
 use std::io::{self, Read};
+use std::ops::Deref;
 use std::path::{Path, PathBuf};
 use std::time::Instant;
 
 use flate2::read::DeflateDecoder;
 
 use rustc_data_structures::owning_ref::OwningRef;
+
 pub struct CrateMismatch {
     path: PathBuf,
     got: String,
@@ -856,6 +858,19 @@ fn get_metadata_section(target: &Target,
     return ret;
 }
 
+/// A trivial wrapper for `Mmap` that implements `StableDeref`.
+struct StableDerefMmap(memmap::Mmap);
+
+impl Deref for StableDerefMmap {
+    type Target = [u8];
+
+    fn deref(&self) -> &[u8] {
+        self.0.deref()
+    }
+}
+
+unsafe impl stable_deref_trait::StableDeref for StableDerefMmap {}
+
 fn get_metadata_section_imp(target: &Target,
                             flavor: CrateFlavor,
                             filename: &Path,
@@ -892,9 +907,14 @@ fn get_metadata_section_imp(target: &Target,
             }
         }
         CrateFlavor::Rmeta => {
-            let buf = fs::read(filename).map_err(|_|
-                format!("failed to read rmeta metadata: '{}'", filename.display()))?;
-            rustc_erase_owner!(OwningRef::new(buf).map_owner_box())
+            // mmap the file, because only a small fraction of it is read.
+            let file = std::fs::File::open(filename).map_err(|_|
+                format!("failed to open rmeta metadata: '{}'", filename.display()))?;
+            let mmap = unsafe { memmap::Mmap::map(&file) };
+            let mmap = mmap.map_err(|_|
+                format!("failed to mmap rmeta metadata: '{}'", filename.display()))?;
+
+            rustc_erase_owner!(OwningRef::new(StableDerefMmap(mmap)).map_owner_box())
         }
     };
     let blob = MetadataBlob(raw_bytes);
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
index cd814de10c3..06dfd4bc2cc 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -112,7 +112,7 @@ mod relate_tys;
 /// - `liveness` -- results of a liveness computation on the MIR; used to create liveness
 ///   constraints for the regions in the types of variables
 /// - `flow_inits` -- results of a maybe-init dataflow analysis
-/// - `move_data` -- move-data constructed when performing the maybe-init dataflow analysiss
+/// - `move_data` -- move-data constructed when performing the maybe-init dataflow analysis
 pub(crate) fn type_check<'gcx, 'tcx>(
     infcx: &InferCtxt<'_, 'gcx, 'tcx>,
     param_env: ty::ParamEnv<'gcx>,
diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs
index c0f059619a4..715d6e0c0d1 100644
--- a/src/librustc_mir/borrow_check/places_conflict.rs
+++ b/src/librustc_mir/borrow_check/places_conflict.rs
@@ -262,7 +262,7 @@ struct PlaceComponents<'p, 'tcx: 'p> {
 impl<'p, 'tcx> PlaceComponents<'p, 'tcx> {
     /// Converts a list of `Place` components into an iterator; this
     /// iterator yields up a never-ending stream of `Option<&Place>`.
-    /// These begin with the "innermst" place and then with each
+    /// These begin with the "innermost" place and then with each
     /// projection therefrom. So given a place like `a.b.c` it would
     /// yield up:
     ///
diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs
index aa383a123b6..2ef71617b7c 100644
--- a/src/librustc_mir/build/block.rs
+++ b/src/librustc_mir/build/block.rs
@@ -90,7 +90,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
 
         let source_info = this.source_info(span);
         for stmt in stmts {
-            let Stmt { kind, opt_destruction_scope } = this.hir.mirror(stmt);
+            let Stmt { kind, opt_destruction_scope, span: stmt_span } = this.hir.mirror(stmt);
             match kind {
                 StmtKind::Expr { scope, expr } => {
                     this.block_context.push(BlockFrame::Statement { ignores_expr_result: true });
@@ -99,7 +99,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                             let si = (scope, source_info);
                             this.in_scope(si, LintLevel::Inherited, block, |this| {
                                 let expr = this.hir.mirror(expr);
-                                this.stmt_expr(block, expr)
+                                this.stmt_expr(block, expr, Some(stmt_span))
                             })
                         }));
                 }
@@ -177,17 +177,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         let destination_ty = destination.ty(&this.local_decls, tcx).to_ty(tcx);
         if let Some(expr) = expr {
             let tail_result_is_ignored = destination_ty.is_unit() ||
-                match this.block_context.last() {
-                    // no context: conservatively assume result is read
-                    None => false,
-
-                    // sub-expression: block result feeds into some computation
-                    Some(BlockFrame::SubExpr) => false,
-
-                    // otherwise: use accumualated is_ignored state.
-                    Some(BlockFrame::TailExpr { tail_result_is_ignored: ignored }) |
-                    Some(BlockFrame::Statement { ignores_expr_result: ignored }) => *ignored,
-                };
+                this.block_context.currently_ignores_tail_results();
             this.block_context.push(BlockFrame::TailExpr { tail_result_is_ignored });
 
             unpack!(block = this.into(destination, block, expr));
diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs
index 8fee74390cc..18ce7ae4907 100644
--- a/src/librustc_mir/build/expr/as_rvalue.rs
+++ b/src/librustc_mir/build/expr/as_rvalue.rs
@@ -351,7 +351,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 block.and(Rvalue::Aggregate(adt, fields))
             }
             ExprKind::Assign { .. } | ExprKind::AssignOp { .. } => {
-                block = unpack!(this.stmt_expr(block, expr));
+                block = unpack!(this.stmt_expr(block, expr, None));
                 block.and(this.unit_rvalue())
             }
             ExprKind::Yield { value } => {
diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs
index e0bf02c6739..8f50a1e9a21 100644
--- a/src/librustc_mir/build/expr/as_temp.rs
+++ b/src/librustc_mir/build/expr/as_temp.rs
@@ -10,7 +10,7 @@
 
 //! See docs in build/expr/mod.rs
 
-use build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
+use build::{BlockAnd, BlockAndExtension, Builder};
 use hair::*;
 use rustc::middle::region;
 use rustc::mir::*;
@@ -68,19 +68,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             debug!("creating temp {:?} with block_context: {:?}", local_decl, this.block_context);
             // Find out whether this temp is being created within the
             // tail expression of a block whose result is ignored.
-            for bf in this.block_context.iter().rev() {
-                match bf {
-                    BlockFrame::SubExpr => continue,
-                    BlockFrame::Statement { .. } => break,
-                    &BlockFrame::TailExpr { tail_result_is_ignored } => {
-                        local_decl = local_decl.block_tail(BlockTailInfo {
-                            tail_result_is_ignored
-                        });
-                        break;
-                    }
-                }
+            if let Some(tail_info) = this.block_context.currently_in_block_tail() {
+                local_decl = local_decl.block_tail(tail_info);
             }
-
             this.local_decls.push(local_decl)
         };
         if !expr_ty.is_never() {
diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs
index d2913872fca..8eb46a04839 100644
--- a/src/librustc_mir/build/expr/into.rs
+++ b/src/librustc_mir/build/expr/into.rs
@@ -351,7 +351,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             | ExprKind::Break { .. }
             | ExprKind::InlineAsm { .. }
             | ExprKind::Return { .. } => {
-                unpack!(block = this.stmt_expr(block, expr));
+                unpack!(block = this.stmt_expr(block, expr, None));
                 this.cfg.push_assign_unit(block, source_info, destination);
                 block.unit()
             }
diff --git a/src/librustc_mir/build/expr/stmt.rs b/src/librustc_mir/build/expr/stmt.rs
index 8f52499124a..45235b31539 100644
--- a/src/librustc_mir/build/expr/stmt.rs
+++ b/src/librustc_mir/build/expr/stmt.rs
@@ -14,7 +14,18 @@ use hair::*;
 use rustc::mir::*;
 
 impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
-    pub fn stmt_expr(&mut self, mut block: BasicBlock, expr: Expr<'tcx>) -> BlockAnd<()> {
+    /// Builds a block of MIR statements to evaluate the HAIR `expr`.
+    /// If the original expression was an AST statement,
+    /// (e.g. `some().code(&here());`) then `opt_stmt_span` is the
+    /// span of that statement (including its semicolon, if any).
+    /// Diagnostics use this span (which may be larger than that of
+    /// `expr`) to identify when statement temporaries are dropped.
+    pub fn stmt_expr(&mut self,
+                     mut block: BasicBlock,
+                     expr: Expr<'tcx>,
+                     opt_stmt_span: Option<StatementSpan>)
+                     -> BlockAnd<()>
+    {
         let this = self;
         let expr_span = expr.span;
         let source_info = this.source_info(expr.span);
@@ -29,7 +40,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             } => {
                 let value = this.hir.mirror(value);
                 this.in_scope((region_scope, source_info), lint_level, block, |this| {
-                    this.stmt_expr(block, value)
+                    this.stmt_expr(block, value, opt_stmt_span)
                 })
             }
             ExprKind::Assign { lhs, rhs } => {
@@ -190,9 +201,56 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             }
             _ => {
                 let expr_ty = expr.ty;
-                let temp = this.temp(expr.ty.clone(), expr_span);
+
+                // Issue #54382: When creating temp for the value of
+                // expression like:
+                //
+                // `{ side_effects(); { let l = stuff(); the_value } }`
+                //
+                // it is usually better to focus on `the_value` rather
+                // than the entirety of block(s) surrounding it.
+                let mut temp_span = expr_span;
+                let mut temp_in_tail_of_block = false;
+                if let ExprKind::Block { body } = expr.kind {
+                    if let Some(tail_expr) = &body.expr {
+                        let mut expr = tail_expr;
+                        while let rustc::hir::ExprKind::Block(subblock, _label) = &expr.node {
+                            if let Some(subtail_expr) = &subblock.expr {
+                                expr = subtail_expr
+                            } else {
+                                break;
+                            }
+                        }
+                        temp_span = expr.span;
+                        temp_in_tail_of_block = true;
+                    }
+                }
+
+                let temp = {
+                    let mut local_decl = LocalDecl::new_temp(expr.ty.clone(), temp_span);
+                    if temp_in_tail_of_block {
+                        if this.block_context.currently_ignores_tail_results() {
+                            local_decl = local_decl.block_tail(BlockTailInfo {
+                                tail_result_is_ignored: true
+                            });
+                        }
+                    }
+                    let temp = this.local_decls.push(local_decl);
+                    let place = Place::Local(temp);
+                    debug!("created temp {:?} for expr {:?} in block_context: {:?}",
+                           temp, expr, this.block_context);
+                    place
+                };
                 unpack!(block = this.into(&temp, block, expr));
-                unpack!(block = this.build_drop(block, expr_span, temp, expr_ty));
+
+                // Attribute drops of the statement's temps to the
+                // semicolon at the statement's end.
+                let drop_point = this.hir.tcx().sess.source_map().end_point(match opt_stmt_span {
+                    None => expr_span,
+                    Some(StatementSpan(span)) => span,
+                });
+
+                unpack!(block = this.build_drop(block, drop_point, temp, expr_ty));
                 block.unit()
             }
         }
diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs
index 177c71b80d1..5d9cb014f58 100644
--- a/src/librustc_mir/build/matches/test.rs
+++ b/src/librustc_mir/build/matches/test.rs
@@ -31,7 +31,7 @@ use std::cmp::Ordering;
 impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
     /// Identifies what test is needed to decide if `match_pair` is applicable.
     ///
-    /// It is a bug to call this with a simplifyable pattern.
+    /// It is a bug to call this with a simplifiable pattern.
     pub fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<'tcx> {
         match *match_pair.pattern.kind {
             PatternKind::Variant { ref adt_def, substs: _, variant_index: _, subpatterns: _ } => {
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index 5b4001f0652..a01f8940a94 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -336,6 +336,9 @@ impl BlockFrame {
     }
  }
 
+#[derive(Debug)]
+struct BlockContext(Vec<BlockFrame>);
+
 struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     hir: Cx<'a, 'gcx, 'tcx>,
     cfg: CFG<'tcx>,
@@ -359,7 +362,7 @@ struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     /// start just throwing new entries onto that vector in order to
     /// distinguish the context of EXPR1 from the context of EXPR2 in
     /// `{ STMTS; EXPR1 } + EXPR2`
-    block_context: Vec<BlockFrame>,
+    block_context: BlockContext,
 
     /// The current unsafe block in scope, even if it is hidden by
     /// a PushUnsafeBlock
@@ -409,6 +412,55 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
     }
 }
 
+impl BlockContext {
+    fn new() -> Self { BlockContext(vec![]) }
+    fn push(&mut self, bf: BlockFrame) { self.0.push(bf); }
+    fn pop(&mut self) -> Option<BlockFrame> { self.0.pop() }
+
+    /// Traverses the frames on the BlockContext, searching for either
+    /// the first block-tail expression frame with no intervening
+    /// statement frame.
+    ///
+    /// Notably, this skips over `SubExpr` frames; this method is
+    /// meant to be used in the context of understanding the
+    /// relationship of a temp (created within some complicated
+    /// expression) with its containing expression, and whether the
+    /// value of that *containing expression* (not the temp!) is
+    /// ignored.
+    fn currently_in_block_tail(&self) -> Option<BlockTailInfo> {
+        for bf in self.0.iter().rev() {
+            match bf {
+                BlockFrame::SubExpr => continue,
+                BlockFrame::Statement { .. } => break,
+                &BlockFrame::TailExpr { tail_result_is_ignored } =>
+                    return Some(BlockTailInfo { tail_result_is_ignored })
+            }
+        }
+
+        return None;
+    }
+
+    /// Looks at the topmost frame on the BlockContext and reports
+    /// whether its one that would discard a block tail result.
+    ///
+    /// Unlike `currently_within_ignored_tail_expression`, this does
+    /// *not* skip over `SubExpr` frames: here, we want to know
+    /// whether the block result itself is discarded.
+    fn currently_ignores_tail_results(&self) -> bool {
+        match self.0.last() {
+            // no context: conservatively assume result is read
+            None => false,
+
+            // sub-expression: block result feeds into some computation
+            Some(BlockFrame::SubExpr) => false,
+
+            // otherwise: use accumulated is_ignored state.
+            Some(BlockFrame::TailExpr { tail_result_is_ignored: ignored }) |
+            Some(BlockFrame::Statement { ignores_expr_result: ignored }) => *ignored,
+        }
+    }
+}
+
 #[derive(Debug)]
 enum LocalsForNode {
     /// In the usual case, a node-id for an identifier maps to at most
@@ -764,7 +816,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             fn_span: span,
             arg_count,
             scopes: vec![],
-            block_context: vec![],
+            block_context: BlockContext::new(),
             source_scopes: IndexVec::new(),
             source_scope: OUTERMOST_SOURCE_SCOPE,
             source_scope_local_data: IndexVec::new(),
diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir/hair/cx/block.rs
index 586d6d87fa0..d56ddcb4944 100644
--- a/src/librustc_mir/hair/cx/block.rs
+++ b/src/librustc_mir/hair/cx/block.rs
@@ -57,6 +57,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
     for (index, stmt) in stmts.iter().enumerate() {
         let hir_id = cx.tcx.hir.node_to_hir_id(stmt.node.id());
         let opt_dxn_ext = cx.region_scope_tree.opt_destruction_scope(hir_id.local_id);
+        let stmt_span = StatementSpan(cx.tcx.hir.span(stmt.node.id()));
         match stmt.node {
             hir::StmtKind::Expr(ref expr, _) |
             hir::StmtKind::Semi(ref expr, _) => {
@@ -69,6 +70,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                         expr: expr.to_ref(),
                     },
                     opt_destruction_scope: opt_dxn_ext,
+                    span: stmt_span,
                 })))
             }
             hir::StmtKind::Decl(ref decl, _) => {
@@ -111,6 +113,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                                 lint_level: cx.lint_level_of(local.id),
                             },
                             opt_destruction_scope: opt_dxn_ext,
+                            span: stmt_span,
                         })));
                     }
                 }
diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs
index 460afba38d6..3078f10598c 100644
--- a/src/librustc_mir/hair/mod.rs
+++ b/src/librustc_mir/hair/mod.rs
@@ -73,9 +73,13 @@ pub enum StmtRef<'tcx> {
 }
 
 #[derive(Clone, Debug)]
+pub struct StatementSpan(pub Span);
+
+#[derive(Clone, Debug)]
 pub struct Stmt<'tcx> {
     pub kind: StmtKind<'tcx>,
     pub opt_destruction_scope: Option<region::Scope>,
+    pub span: StatementSpan,
 }
 
 #[derive(Clone, Debug)]
@@ -116,7 +120,7 @@ pub enum StmtKind<'tcx> {
 /// reference to an expression in this enum is an `ExprRef<'tcx>`, which
 /// may in turn be another instance of this enum (boxed), or else an
 /// unlowered `&'tcx H::Expr`. Note that instances of `Expr` are very
-/// shortlived. They are created by `Hair::to_expr`, analyzed and
+/// short-lived. They are created by `Hair::to_expr`, analyzed and
 /// converted into MIR, and then discarded.
 ///
 /// If you compare `Expr` to the full compiler AST, you will see it is
diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs
index 08736330acb..fd869d6c334 100644
--- a/src/librustc_mir/hair/pattern/_match.rs
+++ b/src/librustc_mir/hair/pattern/_match.rs
@@ -55,11 +55,11 @@
 /// all the values it covers are already covered by row 2.
 ///
 /// To compute `U`, we must have two other concepts.
-///     1. `S(c, P)` is a "specialised matrix", where `c` is a constructor (like `Some` or
+///     1. `S(c, P)` is a "specialized matrix", where `c` is a constructor (like `Some` or
 ///        `None`). You can think of it as filtering `P` to just the rows whose *first* pattern
 ///        can cover `c` (and expanding OR-patterns into distinct patterns), and then expanding
 ///        the constructor into all of its components.
-///        The specialisation of a row vector is computed by `specialize`.
+///        The specialization of a row vector is computed by `specialize`.
 ///
 ///        It is computed as follows. For each row `p_i` of P, we have four cases:
 ///             1.1. `p_(i,1) = c(r_1, .., r_a)`. Then `S(c, P)` has a corresponding row:
@@ -1453,7 +1453,7 @@ fn should_treat_range_exhaustively(tcx: TyCtxt<'_, 'tcx, 'tcx>, ctor: &Construct
 /// mean creating a separate constructor for every single value in the range, which is clearly
 /// impractical. However, observe that for some ranges of integers, the specialisation will be
 /// identical across all values in that range (i.e. there are equivalence classes of ranges of
-/// constructors based on their `is_useful_specialised` outcome). These classes are grouped by
+/// constructors based on their `is_useful_specialized` outcome). These classes are grouped by
 /// the patterns that apply to them (in the matrix `P`). We can split the range whenever the
 /// patterns that apply to that range (specifically: the patterns that *intersect* with that range)
 /// change.
diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs
index c3554512806..988ff7e7516 100644
--- a/src/librustc_mir/interpret/validity.rs
+++ b/src/librustc_mir/interpret/validity.rs
@@ -67,7 +67,7 @@ macro_rules! try_validation {
     }}
 }
 
-/// We want to show a nice path to the invalid field for diagnotsics,
+/// We want to show a nice path to the invalid field for diagnostics,
 /// but avoid string operations in the happy case where no error happens.
 /// So we track a `Vec<PathElem>` where `PathElem` contains all the data we
 /// need to later print something for the user.
diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs
index ca58239df8e..a90cccfa7a7 100644
--- a/src/librustc_passes/rvalue_promotion.rs
+++ b/src/librustc_passes/rvalue_promotion.rs
@@ -172,7 +172,7 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> {
     /// While the `ExprUseVisitor` walks, we will identify which
     /// expressions are borrowed, and insert their ids into this
     /// table. Actually, we insert the "borrow-id", which is normally
-    /// the id of the expession being borrowed: but in the case of
+    /// the id of the expression being borrowed: but in the case of
     /// `ref mut` borrows, the `id` of the pattern is
     /// inserted. Therefore later we remove that entry from the table
     /// and transfer it over to the value being matched. This will
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index a3694cd73ad..5a91b50f6bc 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -663,7 +663,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
         let mut errors = false;
         let mut seen_spans = FxHashSet::default();
         let mut error_vec = Vec::new();
-        let mut prev_root_id: NodeId = NodeId::new(0);
+        let mut prev_root_id: NodeId = NodeId::from_u32(0);
         for i in 0 .. self.determined_imports.len() {
             let import = self.determined_imports[i];
             let error = self.finalize_import(import);
diff --git a/src/librustc_traits/lowering/mod.rs b/src/librustc_traits/lowering/mod.rs
index 83b90cf1bf2..cf1bc04dd4e 100644
--- a/src/librustc_traits/lowering/mod.rs
+++ b/src/librustc_traits/lowering/mod.rs
@@ -217,8 +217,9 @@ fn program_clauses_for_trait<'a, 'tcx>(
 
     let implemented_from_env = Clause::ForAll(ty::Binder::bind(implemented_from_env));
 
-    let where_clauses = &tcx.predicates_defined_on(def_id).predicates
-        .into_iter()
+    let predicates = &tcx.predicates_defined_on(def_id).predicates;
+    let where_clauses = &predicates
+        .iter()
         .map(|(wc, _)| wc.lower())
         .map(|wc| wc.subst(tcx, bound_vars))
         .collect::<Vec<_>>();
@@ -314,8 +315,9 @@ fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId
     let trait_pred = ty::TraitPredicate { trait_ref }.lower();
 
     // `WC`
-    let where_clauses = tcx.predicates_of(def_id).predicates
-        .into_iter()
+    let predicates = &tcx.predicates_of(def_id).predicates;
+    let where_clauses = predicates
+        .iter()
         .map(|(wc, _)| wc.lower())
         .map(|wc| wc.subst(tcx, bound_vars));
 
@@ -352,7 +354,7 @@ pub fn program_clauses_for_type_def<'a, 'tcx>(
 
     // `WC`
     let where_clauses = tcx.predicates_of(def_id).predicates
-        .into_iter()
+        .iter()
         .map(|(wc, _)| wc.lower())
         .map(|wc| wc.subst(tcx, bound_vars))
         .collect::<Vec<_>>();
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 572e79407a1..d388d756438 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -24,6 +24,7 @@ use rustc::traits;
 use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable};
 use rustc::ty::{GenericParamDef, GenericParamDefKind};
 use rustc::ty::wf::object_region_bounds;
+use rustc_data_structures::sync::Lrc;
 use rustc_target::spec::abi;
 use std::collections::BTreeSet;
 use std::slice;
@@ -45,7 +46,7 @@ pub trait AstConv<'gcx, 'tcx> {
     /// Returns the set of bounds in scope for the type parameter with
     /// the given id.
     fn get_type_parameter_bounds(&self, span: Span, def_id: DefId)
-                                 -> ty::GenericPredicates<'tcx>;
+                                 -> Lrc<ty::GenericPredicates<'tcx>>;
 
     /// What lifetime should we use when a lifetime is omitted (and not elided)?
     fn re_infer(&self, span: Span, _def: Option<&ty::GenericParamDef>)
@@ -1119,8 +1120,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
     {
         let tcx = self.tcx();
 
-        let bounds = self.get_type_parameter_bounds(span, ty_param_def_id)
-            .predicates.into_iter().filter_map(|(p, _)| p.to_opt_poly_trait_ref());
+        let predicates = &self.get_type_parameter_bounds(span, ty_param_def_id).predicates;
+        let bounds = predicates.iter().filter_map(|(p, _)| p.to_opt_poly_trait_ref());
 
         // Check that there is exactly one way to find an associated type with the
         // correct name.
diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index 84967aaf72f..9aad17626f9 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -134,6 +134,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             "rustc_peek" => (1, vec![param(0)], param(0)),
             "init" => (1, Vec::new(), param(0)),
             "uninit" => (1, Vec::new(), param(0)),
+            "forget" => (1, vec![param(0)], tcx.mk_unit()),
             "transmute" => (2, vec![ param(0) ], param(1)),
             "move_val_init" => {
                 (1,
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 4c06cae1d07..0373bf4e752 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -1440,7 +1440,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
     ///
     /// 1. Because the numbers of the region variables would otherwise be fairly unique to this
     ///    particular method call, it winds up creating fewer types overall, which helps for memory
-    ///    usage. (Admittedly, this is a rather small effect, though measureable.)
+    ///    usage. (Admittedly, this is a rather small effect, though measurable.)
     ///
     /// 2. It makes it easier to deal with higher-ranked trait bounds, because we can replace any
     ///    late-bound regions with 'static. Otherwise, if we were going to replace late-bound
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index e3a6f92d79e..eed5d909063 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1869,7 +1869,7 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
     fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx }
 
     fn get_type_parameter_bounds(&self, _: Span, def_id: DefId)
-                                 -> ty::GenericPredicates<'tcx>
+                                 -> Lrc<ty::GenericPredicates<'tcx>>
     {
         let tcx = self.tcx;
         let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
@@ -1877,7 +1877,7 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
         let item_def_id = tcx.hir.local_def_id(item_id);
         let generics = tcx.generics_of(item_def_id);
         let index = generics.param_def_id_to_index[&def_id];
-        ty::GenericPredicates {
+        Lrc::new(ty::GenericPredicates {
             parent: None,
             predicates: self.param_env.caller_bounds.iter().filter_map(|&predicate| {
                 match predicate {
@@ -1890,7 +1890,7 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
                     _ => None
                 }
             }).collect()
-        }
+        })
     }
 
     fn re_infer(&self, span: Span, def: Option<&ty::GenericParamDef>)
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 8574443190d..b5addbd18d2 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -910,8 +910,8 @@ fn check_false_global_bounds<'a, 'gcx, 'tcx>(
 
     let def_id = fcx.tcx.hir.local_def_id(id);
     let predicates = fcx.tcx.predicates_of(def_id).predicates
-        .into_iter()
-        .map(|(p, _)| p)
+        .iter()
+        .map(|(p, _)| *p)
         .collect();
     // Check elaborated bounds
     let implied_obligations = traits::elaborate_predicates(fcx.tcx, predicates);
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index d2dc226aca2..6ef09d96fd1 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -39,6 +39,7 @@ use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt};
 use rustc::ty::{ReprOptions, ToPredicate};
 use rustc::util::captures::Captures;
 use rustc::util::nodemap::FxHashMap;
+use rustc_data_structures::sync::Lrc;
 use rustc_target::spec::abi;
 
 use syntax::ast;
@@ -178,7 +179,8 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> {
         self.tcx
     }
 
-    fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) -> ty::GenericPredicates<'tcx> {
+    fn get_type_parameter_bounds(&self, span: Span, def_id: DefId)
+                                 -> Lrc<ty::GenericPredicates<'tcx>> {
         self.tcx
             .at(span)
             .type_param_predicates((self.item_def_id, def_id))
@@ -243,7 +245,7 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> {
 fn type_param_predicates<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     (item_def_id, def_id): (DefId, DefId),
-) -> ty::GenericPredicates<'tcx> {
+) -> Lrc<ty::GenericPredicates<'tcx>> {
     use rustc::hir::*;
 
     // In the AST, bounds can derive from two places. Either
@@ -264,11 +266,11 @@ fn type_param_predicates<'a, 'tcx>(
         tcx.generics_of(item_def_id).parent
     };
 
-    let mut result = parent.map_or(
-        ty::GenericPredicates {
+    let mut result = parent.map_or_else(
+        || Lrc::new(ty::GenericPredicates {
             parent: None,
             predicates: vec![],
-        },
+        }),
         |parent| {
             let icx = ItemCtxt::new(tcx, parent);
             icx.get_type_parameter_bounds(DUMMY_SP, def_id)
@@ -298,7 +300,7 @@ fn type_param_predicates<'a, 'tcx>(
                     // Implied `Self: Trait` and supertrait bounds.
                     if param_id == item_node_id {
                         let identity_trait_ref = ty::TraitRef::identity(tcx, item_def_id);
-                        result
+                        Lrc::make_mut(&mut result)
                             .predicates
                             .push((identity_trait_ref.to_predicate(), item.span));
                     }
@@ -317,7 +319,7 @@ fn type_param_predicates<'a, 'tcx>(
     };
 
     let icx = ItemCtxt::new(tcx, item_def_id);
-    result
+    Lrc::make_mut(&mut result)
         .predicates
         .extend(icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty,
             OnlySelfBounds(true)));
@@ -685,7 +687,7 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::Ad
 fn super_predicates_of<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     trait_def_id: DefId,
-) -> ty::GenericPredicates<'tcx> {
+) -> Lrc<ty::GenericPredicates<'tcx>> {
     debug!("super_predicates(trait_def_id={:?})", trait_def_id);
     let trait_node_id = tcx.hir.as_local_node_id(trait_def_id).unwrap();
 
@@ -729,10 +731,10 @@ fn super_predicates_of<'a, 'tcx>(
         }
     }
 
-    ty::GenericPredicates {
+    Lrc::new(ty::GenericPredicates {
         parent: None,
         predicates: superbounds,
-    }
+    })
 }
 
 fn trait_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::TraitDef {
@@ -1605,27 +1607,23 @@ fn early_bound_lifetimes_from_generics<'a, 'tcx>(
 fn predicates_defined_on<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     def_id: DefId,
-) -> ty::GenericPredicates<'tcx> {
-    let explicit = tcx.explicit_predicates_of(def_id);
-    let span = tcx.def_span(def_id);
-    let predicates = explicit.predicates.into_iter().chain(
-        tcx.inferred_outlives_of(def_id).iter().map(|&p| (p, span))
-    ).collect();
-
-    ty::GenericPredicates {
-        parent: explicit.parent,
-        predicates: predicates,
+) -> Lrc<ty::GenericPredicates<'tcx>> {
+    let mut result = tcx.explicit_predicates_of(def_id);
+    let inferred_outlives = tcx.inferred_outlives_of(def_id);
+    if !inferred_outlives.is_empty() {
+        let span = tcx.def_span(def_id);
+        Lrc::make_mut(&mut result)
+            .predicates
+            .extend(inferred_outlives.iter().map(|&p| (p, span)));
     }
+    result
 }
 
 fn predicates_of<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     def_id: DefId,
-) -> ty::GenericPredicates<'tcx> {
-    let ty::GenericPredicates {
-        parent,
-        mut predicates,
-    } = tcx.predicates_defined_on(def_id);
+) -> Lrc<ty::GenericPredicates<'tcx>> {
+    let mut result = tcx.predicates_defined_on(def_id);
 
     if tcx.is_trait(def_id) {
         // For traits, add `Self: Trait` predicate. This is
@@ -1641,16 +1639,17 @@ fn predicates_of<'a, 'tcx>(
         // used, and adding the predicate into this list ensures
         // that this is done.
         let span = tcx.def_span(def_id);
-        predicates.push((ty::TraitRef::identity(tcx, def_id).to_predicate(), span));
+        Lrc::make_mut(&mut result)
+            .predicates
+            .push((ty::TraitRef::identity(tcx, def_id).to_predicate(), span));
     }
-
-    ty::GenericPredicates { parent, predicates }
+    result
 }
 
 fn explicit_predicates_of<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     def_id: DefId,
-) -> ty::GenericPredicates<'tcx> {
+) -> Lrc<ty::GenericPredicates<'tcx>> {
     use rustc::hir::*;
     use rustc_data_structures::fx::FxHashSet;
 
@@ -1761,10 +1760,10 @@ fn explicit_predicates_of<'a, 'tcx>(
 
                     if impl_trait_fn.is_some() {
                         // impl Trait
-                        return ty::GenericPredicates {
+                        return Lrc::new(ty::GenericPredicates {
                             parent: None,
                             predicates: bounds.predicates(tcx, opaque_ty),
-                        };
+                        });
                     } else {
                         // named existential types
                         predicates.extend(bounds.predicates(tcx, opaque_ty));
@@ -1794,7 +1793,7 @@ fn explicit_predicates_of<'a, 'tcx>(
     // on a trait we need to add in the supertrait bounds and bounds found on
     // associated types.
     if let Some((_trait_ref, _)) = is_trait {
-        predicates.extend(tcx.super_predicates_of(def_id).predicates);
+        predicates.extend(tcx.super_predicates_of(def_id).predicates.iter().cloned());
     }
 
     // In default impls, we can assume that the self type implements
@@ -1971,10 +1970,10 @@ fn explicit_predicates_of<'a, 'tcx>(
         );
     }
 
-    ty::GenericPredicates {
+    Lrc::new(ty::GenericPredicates {
         parent: generics.parent,
         predicates,
-    }
+    })
 }
 
 pub enum SizedByDefault {
diff --git a/src/librustc_typeck/outlives/explicit.rs b/src/librustc_typeck/outlives/explicit.rs
index 75f8b78b9ec..9b374cf932f 100644
--- a/src/librustc_typeck/outlives/explicit.rs
+++ b/src/librustc_typeck/outlives/explicit.rs
@@ -33,14 +33,14 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> {
     ) -> &RequiredPredicates<'tcx> {
         self.map.entry(def_id).or_insert_with(|| {
             let predicates = if def_id.is_local() {
-                tcx.explicit_predicates_of(def_id).predicates
+                tcx.explicit_predicates_of(def_id)
             } else {
-                tcx.predicates_of(def_id).predicates
+                tcx.predicates_of(def_id)
             };
             let mut required_predicates = RequiredPredicates::default();
 
             // process predicates and convert to `RequiredPredicates` entry, see below
-            for (pred, _) in predicates.into_iter() {
+            for (pred, _) in predicates.predicates.iter() {
                 match pred {
                     ty::Predicate::TypeOutlives(predicate) => {
                         let OutlivesPredicate(ref ty, ref reg) = predicate.skip_binder();
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 931ba21f6e4..0518d73e1e3 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1563,7 +1563,7 @@ impl Clean<Generics> for hir::Generics {
 }
 
 impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
-                                    &'a ty::GenericPredicates<'tcx>) {
+                                    &'a Lrc<ty::GenericPredicates<'tcx>>) {
     fn clean(&self, cx: &DocContext) -> Generics {
         use self::WherePredicate as WP;
 
diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs
index eda522af922..635608d140d 100644
--- a/src/librustdoc/clean/simplify.rs
+++ b/src/librustdoc/clean/simplify.rs
@@ -156,8 +156,8 @@ fn trait_is_same_or_supertrait(cx: &DocContext, child: DefId,
     if child == trait_ {
         return true
     }
-    let predicates = cx.tcx.super_predicates_of(child).predicates;
-    predicates.iter().filter_map(|(pred, _)| {
+    let predicates = cx.tcx.super_predicates_of(child);
+    predicates.predicates.iter().filter_map(|(pred, _)| {
         if let ty::Predicate::Trait(ref pred) = *pred {
             if pred.skip_binder().trait_ref.self_ty().is_self() {
                 Some(pred.def_id())
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 7dafe67485a..f4d05c6dbd6 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -187,7 +187,7 @@ pub struct RenderOptions {
     /// Whether to generate a table of contents on the output file when reading a standalone
     /// Markdown file.
     pub markdown_no_toc: bool,
-    /// Additional CSS files to link in pages generated from standlone Markdown files.
+    /// Additional CSS files to link in pages generated from standalone Markdown files.
     pub markdown_css: Vec<String>,
     /// If present, playground URL to use in the "Run" button added to code samples generated from
     /// standalone Markdown files. If not present, `playground_url` is used.
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index 0f9104f91b4..b2473dd9b23 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -961,7 +961,7 @@ span.since {
 		padding-top: 0px;
 	}
 
-	body > .sidebar {
+	.rustdoc > .sidebar {
 		height: 45px;
 		min-height: 40px;
 		margin: 0;
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index a780322e85e..471ba6345e2 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -243,7 +243,7 @@ fn look_for_tests<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx>(
         if tests.found_tests == 0 {
             let mut diag = cx.tcx.struct_span_lint_node(
                 lint::builtin::MISSING_DOC_CODE_EXAMPLES,
-                NodeId::new(0),
+                NodeId::from_u32(0),
                 span_of_attrs(&item.attrs),
                 "Missing code example in this documentation");
             diag.emit();
@@ -281,14 +281,14 @@ impl<'a, 'tcx, 'rcx, 'cstore> DocFolder for LinkCollector<'a, 'tcx, 'rcx, 'cstor
         let current_item = match item.inner {
             ModuleItem(..) => {
                 if item.attrs.inner_docs {
-                    if item_node_id.unwrap() != NodeId::new(0) {
+                    if item_node_id.unwrap() != NodeId::from_u32(0) {
                         item.name.clone()
                     } else {
                         None
                     }
                 } else {
                     match parent_node.or(self.mod_ids.last().cloned()) {
-                        Some(parent) if parent != NodeId::new(0) => {
+                        Some(parent) if parent != NodeId::from_u32(0) => {
                             //FIXME: can we pull the parent module's name from elsewhere?
                             Some(self.cx.tcx.hir.name(parent).to_string())
                         }
@@ -538,13 +538,13 @@ fn resolution_failure(
             );
 
             diag = cx.tcx.struct_span_lint_node(lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE,
-                                                NodeId::new(0),
+                                                NodeId::from_u32(0),
                                                 sp,
                                                 &msg);
             diag.span_label(sp, "cannot be resolved, ignoring");
         } else {
             diag = cx.tcx.struct_span_lint_node(lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE,
-                                                NodeId::new(0),
+                                                NodeId::from_u32(0),
                                                 sp,
                                                 &msg);
 
@@ -564,7 +564,7 @@ fn resolution_failure(
         diag
     } else {
         cx.tcx.struct_span_lint_node(lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE,
-                                     NodeId::new(0),
+                                     NodeId::from_u32(0),
                                      sp,
                                      &msg)
     };
diff --git a/src/libstd/alloc.rs b/src/libstd/alloc.rs
index 9c057396470..b024574427e 100644
--- a/src/libstd/alloc.rs
+++ b/src/libstd/alloc.rs
@@ -85,7 +85,7 @@ pub use alloc_crate::alloc::*;
 /// This is based on `malloc` on Unix platforms and `HeapAlloc` on Windows,
 /// plus related functions.
 ///
-/// This type implements the `GlobalAlloc` trait and Rust programs by deafult
+/// This type implements the `GlobalAlloc` trait and Rust programs by default
 /// work as if they had this definition:
 ///
 /// ```rust
diff --git a/src/libstd/build.rs b/src/libstd/build.rs
index b3851d22841..9d6e8c4cafd 100644
--- a/src/libstd/build.rs
+++ b/src/libstd/build.rs
@@ -41,8 +41,11 @@ fn main() {
     } else if target.contains("freebsd") {
         println!("cargo:rustc-link-lib=execinfo");
         println!("cargo:rustc-link-lib=pthread");
+    } else if target.contains("netbsd") {
+        println!("cargo:rustc-link-lib=pthread");
+        println!("cargo:rustc-link-lib=rt");
     } else if target.contains("dragonfly") || target.contains("bitrig") ||
-              target.contains("netbsd") || target.contains("openbsd") {
+              target.contains("openbsd") {
         println!("cargo:rustc-link-lib=pthread");
     } else if target.contains("solaris") {
         println!("cargo:rustc-link-lib=socket");
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index 8de415e8aed..bb2f152edc6 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -1569,7 +1569,7 @@ impl<K, V, S> HashMap<K, V, S>
     /// where the key should go, meaning the keys may become "lost" if their
     /// location does not reflect their state. For instance, if you change a key
     /// so that the map now contains keys which compare equal, search may start
-    /// acting eratically, with two keys randomly masking eachother. Implementations
+    /// acting erratically, with two keys randomly masking each other. Implementations
     /// are free to assume this doesn't happen (within the limits of memory-safety).
     #[unstable(feature = "hash_raw_entry", issue = "54043")]
     pub fn raw_entry_mut(&mut self) -> RawEntryBuilderMut<K, V, S> {
diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs
index e26e6d391f8..476ee3f71ca 100644
--- a/src/libstd/io/buffered.rs
+++ b/src/libstd/io/buffered.rs
@@ -525,6 +525,25 @@ impl<W: Write> BufWriter<W> {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get_mut(&mut self) -> &mut W { self.inner.as_mut().unwrap() }
 
+    /// Returns a reference to the internally buffered data.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// # #![feature(bufreader_buffer)]
+    /// use std::io::BufWriter;
+    /// use std::net::TcpStream;
+    ///
+    /// let buf_writer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
+    ///
+    /// // See how many bytes are currently buffered
+    /// let bytes_buffered = buf_writer.buffer().len();
+    /// ```
+    #[unstable(feature = "bufreader_buffer", issue = "45323")]
+    pub fn buffer(&self) -> &[u8] {
+        &self.buf
+    }
+
     /// Unwraps this `BufWriter`, returning the underlying writer.
     ///
     /// The buffer is written out before returning the writer.
@@ -965,31 +984,31 @@ mod tests {
         let mut buf = [0, 0, 0];
         let nread = reader.read(&mut buf);
         assert_eq!(nread.unwrap(), 3);
-        let b: &[_] = &[5, 6, 7];
-        assert_eq!(buf, b);
+        assert_eq!(buf, [5, 6, 7]);
+        assert_eq!(reader.buffer(), []);
 
         let mut buf = [0, 0];
         let nread = reader.read(&mut buf);
         assert_eq!(nread.unwrap(), 2);
-        let b: &[_] = &[0, 1];
-        assert_eq!(buf, b);
+        assert_eq!(buf, [0, 1]);
+        assert_eq!(reader.buffer(), []);
 
         let mut buf = [0];
         let nread = reader.read(&mut buf);
         assert_eq!(nread.unwrap(), 1);
-        let b: &[_] = &[2];
-        assert_eq!(buf, b);
+        assert_eq!(buf, [2]);
+        assert_eq!(reader.buffer(), [3]);
 
         let mut buf = [0, 0, 0];
         let nread = reader.read(&mut buf);
         assert_eq!(nread.unwrap(), 1);
-        let b: &[_] = &[3, 0, 0];
-        assert_eq!(buf, b);
+        assert_eq!(buf, [3, 0, 0]);
+        assert_eq!(reader.buffer(), []);
 
         let nread = reader.read(&mut buf);
         assert_eq!(nread.unwrap(), 1);
-        let b: &[_] = &[4, 0, 0];
-        assert_eq!(buf, b);
+        assert_eq!(buf, [4, 0, 0]);
+        assert_eq!(reader.buffer(), []);
 
         assert_eq!(reader.read(&mut buf).unwrap(), 0);
     }
@@ -1078,31 +1097,40 @@ mod tests {
         let mut writer = BufWriter::with_capacity(2, inner);
 
         writer.write(&[0, 1]).unwrap();
+        assert_eq!(writer.buffer(), []);
         assert_eq!(*writer.get_ref(), [0, 1]);
 
         writer.write(&[2]).unwrap();
+        assert_eq!(writer.buffer(), [2]);
         assert_eq!(*writer.get_ref(), [0, 1]);
 
         writer.write(&[3]).unwrap();
+        assert_eq!(writer.buffer(), [2, 3]);
         assert_eq!(*writer.get_ref(), [0, 1]);
 
         writer.flush().unwrap();
+        assert_eq!(writer.buffer(), []);
         assert_eq!(*writer.get_ref(), [0, 1, 2, 3]);
 
         writer.write(&[4]).unwrap();
         writer.write(&[5]).unwrap();
+        assert_eq!(writer.buffer(), [4, 5]);
         assert_eq!(*writer.get_ref(), [0, 1, 2, 3]);
 
         writer.write(&[6]).unwrap();
+        assert_eq!(writer.buffer(), [6]);
         assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5]);
 
         writer.write(&[7, 8]).unwrap();
+        assert_eq!(writer.buffer(), []);
         assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5, 6, 7, 8]);
 
         writer.write(&[9, 10, 11]).unwrap();
+        assert_eq!(writer.buffer(), []);
         assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
 
         writer.flush().unwrap();
+        assert_eq!(writer.buffer(), []);
         assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
     }
 
diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs
index 6c95854c66c..13cf3133dcd 100644
--- a/src/libstd/keyword_docs.rs
+++ b/src/libstd/keyword_docs.rs
@@ -615,7 +615,7 @@ mod loop_keyword { }
 //
 /// The keyword used to define structs.
 ///
-/// Structs in Rust come in three flavours: Structs with named fields, tuple structs, and unit
+/// Structs in Rust come in three flavors: Structs with named fields, tuple structs, and unit
 /// structs.
 ///
 /// ```rust
diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs
index 2517c45696a..8685cb73887 100644
--- a/src/libstd/net/ip.rs
+++ b/src/libstd/net/ip.rs
@@ -852,7 +852,7 @@ impl From<[u8; 4]> for IpAddr {
 impl Ipv6Addr {
     /// Creates a new IPv6 address from eight 16-bit segments.
     ///
-    /// The result will represent the IP address a:b:c:d:e:f:g:h.
+    /// The result will represent the IP address `a:b:c:d:e:f:g:h`.
     ///
     /// # Examples
     ///
diff --git a/src/libstd/process.rs b/src/libstd/process.rs
index 327ad7f64c2..51481e129df 100644
--- a/src/libstd/process.rs
+++ b/src/libstd/process.rs
@@ -1122,7 +1122,7 @@ impl From<fs::File> for Stdio {
     /// let file = File::open("foo.txt").unwrap();
     ///
     /// let reverse = Command::new("rev")
-    ///     .stdin(file)  // Implicit File convertion into a Stdio
+    ///     .stdin(file)  // Implicit File conversion into a Stdio
     ///     .output()
     ///     .expect("failed reverse command");
     ///
@@ -1340,7 +1340,7 @@ impl Child {
     /// Attempts to collect the exit status of the child if it has already
     /// exited.
     ///
-    /// This function will not block the calling thread and will only advisorily
+    /// This function will not block the calling thread and will only
     /// check to see if the child process has exited or not. If the child has
     /// exited then on Unix the process id is reaped. This function is
     /// guaranteed to repeatedly return a successful exit status so long as the
diff --git a/src/libstd/sys/redox/fd.rs b/src/libstd/sys/redox/fd.rs
index d61103a872f..d62b09134bb 100644
--- a/src/libstd/sys/redox/fd.rs
+++ b/src/libstd/sys/redox/fd.rs
@@ -26,7 +26,7 @@ impl FileDesc {
 
     pub fn raw(&self) -> usize { self.fd }
 
-    /// Extracts the actual filedescriptor without closing it.
+    /// Extracts the actual file descriptor without closing it.
     pub fn into_raw(self) -> usize {
         let fd = self.fd;
         mem::forget(self);
diff --git a/src/libstd/sys/redox/mod.rs b/src/libstd/sys/redox/mod.rs
index edb407ecd23..3543d8f8fa3 100644
--- a/src/libstd/sys/redox/mod.rs
+++ b/src/libstd/sys/redox/mod.rs
@@ -77,6 +77,29 @@ pub fn cvt(result: Result<usize, syscall::Error>) -> io::Result<usize> {
     result.map_err(|err| io::Error::from_raw_os_error(err.errno))
 }
 
+#[doc(hidden)]
+pub trait IsMinusOne {
+    fn is_minus_one(&self) -> bool;
+}
+
+macro_rules! impl_is_minus_one {
+    ($($t:ident)*) => ($(impl IsMinusOne for $t {
+        fn is_minus_one(&self) -> bool {
+            *self == -1
+        }
+    })*)
+}
+
+impl_is_minus_one! { i8 i16 i32 i64 isize }
+
+pub fn cvt_libc<T: IsMinusOne>(t: T) -> io::Result<T> {
+    if t.is_minus_one() {
+        Err(io::Error::last_os_error())
+    } else {
+        Ok(t)
+    }
+}
+
 /// On Redox, use an illegal instruction to abort
 pub unsafe fn abort_internal() -> ! {
     ::core::intrinsics::abort();
diff --git a/src/libstd/sys/redox/os.rs b/src/libstd/sys/redox/os.rs
index 5822216779b..84eb56615b6 100644
--- a/src/libstd/sys/redox/os.rs
+++ b/src/libstd/sys/redox/os.rs
@@ -12,10 +12,12 @@
 
 #![allow(unused_imports)] // lots of cfg code here
 
+use libc::{self, c_char};
+
 use os::unix::prelude::*;
 
 use error::Error as StdError;
-use ffi::{OsString, OsStr};
+use ffi::{CStr, CString, OsStr, OsString};
 use fmt;
 use io::{self, Read, Write};
 use iter;
@@ -27,7 +29,7 @@ use ptr;
 use slice;
 use str;
 use sys_common::mutex::Mutex;
-use sys::{cvt, fd, syscall};
+use sys::{cvt, cvt_libc, fd, syscall};
 use vec;
 
 extern {
@@ -129,6 +131,8 @@ pub fn current_exe() -> io::Result<PathBuf> {
     Ok(PathBuf::from(path))
 }
 
+pub static ENV_LOCK: Mutex = Mutex::new();
+
 pub struct Env {
     iter: vec::IntoIter<(OsString, OsString)>,
     _dont_send_or_sync_me: PhantomData<*mut ()>,
@@ -140,52 +144,83 @@ impl Iterator for Env {
     fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
 }
 
+pub unsafe fn environ() -> *mut *const *const c_char {
+    extern { static mut environ: *const *const c_char; }
+    &mut environ
+}
+
 /// Returns a vector of (variable, value) byte-vector pairs for all the
 /// environment variables of the current process.
 pub fn env() -> Env {
-    let mut variables: Vec<(OsString, OsString)> = Vec::new();
-    if let Ok(mut file) = ::fs::File::open("env:") {
-        let mut string = String::new();
-        if file.read_to_string(&mut string).is_ok() {
-            for line in string.lines() {
-                let mut parts = line.splitn(2, '=');
-                if let Some(name) = parts.next() {
-                    let value = parts.next().unwrap_or("");
-                    variables.push((OsString::from(name.to_string()),
-                                    OsString::from(value.to_string())));
-                }
+    unsafe {
+        let _guard = ENV_LOCK.lock();
+        let mut environ = *environ();
+        if environ == ptr::null() {
+            panic!("os::env() failure getting env string from OS: {}",
+                   io::Error::last_os_error());
+        }
+        let mut result = Vec::new();
+        while *environ != ptr::null() {
+            if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) {
+                result.push(key_value);
             }
+            environ = environ.offset(1);
+        }
+        return Env {
+            iter: result.into_iter(),
+            _dont_send_or_sync_me: PhantomData,
+        }
+    }
+
+    fn parse(input: &[u8]) -> Option<(OsString, OsString)> {
+        // Strategy (copied from glibc): Variable name and value are separated
+        // by an ASCII equals sign '='. Since a variable name must not be
+        // empty, allow variable names starting with an equals sign. Skip all
+        // malformed lines.
+        if input.is_empty() {
+            return None;
         }
+        let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1);
+        pos.map(|p| (
+            OsStringExt::from_vec(input[..p].to_vec()),
+            OsStringExt::from_vec(input[p+1..].to_vec()),
+        ))
     }
-    Env { iter: variables.into_iter(), _dont_send_or_sync_me: PhantomData }
 }
 
-pub fn getenv(key: &OsStr) -> io::Result<Option<OsString>> {
-    if ! key.is_empty() {
-        if let Ok(mut file) = ::fs::File::open(&("env:".to_owned() + key.to_str().unwrap())) {
-            let mut string = String::new();
-            file.read_to_string(&mut string)?;
-            Ok(Some(OsString::from(string)))
+pub fn getenv(k: &OsStr) -> io::Result<Option<OsString>> {
+    // environment variables with a nul byte can't be set, so their value is
+    // always None as well
+    let k = CString::new(k.as_bytes())?;
+    unsafe {
+        let _guard = ENV_LOCK.lock();
+        let s = libc::getenv(k.as_ptr()) as *const libc::c_char;
+        let ret = if s.is_null() {
+            None
         } else {
-            Ok(None)
-        }
-    } else {
-        Ok(None)
+            Some(OsStringExt::from_vec(CStr::from_ptr(s).to_bytes().to_vec()))
+        };
+        Ok(ret)
     }
 }
 
-pub fn setenv(key: &OsStr, value: &OsStr) -> io::Result<()> {
-    if ! key.is_empty() {
-        let mut file = ::fs::File::create(&("env:".to_owned() + key.to_str().unwrap()))?;
-        file.write_all(value.as_bytes())?;
-        file.set_len(value.len() as u64)?;
+pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
+    let k = CString::new(k.as_bytes())?;
+    let v = CString::new(v.as_bytes())?;
+
+    unsafe {
+        let _guard = ENV_LOCK.lock();
+        cvt_libc(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(|_| ())
     }
-    Ok(())
 }
 
-pub fn unsetenv(key: &OsStr) -> io::Result<()> {
-    ::fs::remove_file(&("env:".to_owned() + key.to_str().unwrap()))?;
-    Ok(())
+pub fn unsetenv(n: &OsStr) -> io::Result<()> {
+    let nbuf = CString::new(n.as_bytes())?;
+
+    unsafe {
+        let _guard = ENV_LOCK.lock();
+        cvt_libc(libc::unsetenv(nbuf.as_ptr())).map(|_| ())
+    }
 }
 
 pub fn page_size() -> usize {
diff --git a/src/libstd/sys/redox/process.rs b/src/libstd/sys/redox/process.rs
index 2037616e6ac..4370c1e0502 100644
--- a/src/libstd/sys/redox/process.rs
+++ b/src/libstd/sys/redox/process.rs
@@ -9,15 +9,19 @@
 // except according to those terms.
 
 use env::{split_paths};
-use ffi::OsStr;
-use os::unix::ffi::OsStrExt;
+use ffi::{CStr, OsStr};
 use fmt;
-use io::{self, Error, ErrorKind};
-use iter;
+use fs::File;
+use io::{self, prelude::*, BufReader, Error, ErrorKind, SeekFrom};
 use libc::{EXIT_SUCCESS, EXIT_FAILURE};
+use os::unix::ffi::OsStrExt;
 use path::{Path, PathBuf};
+use ptr;
+use sys::ext::fs::MetadataExt;
+use sys::ext::io::AsRawFd;
 use sys::fd::FileDesc;
-use sys::fs::{File, OpenOptions};
+use sys::fs::{File as SysFile, OpenOptions};
+use sys::os::{ENV_LOCK, environ};
 use sys::pipe::{self, AnonPipe};
 use sys::{cvt, syscall};
 use sys_common::process::{CommandEnv, DefaultEnvKey};
@@ -297,12 +301,6 @@ impl Command {
             t!(callback());
         }
 
-        let args: Vec<[usize; 2]> = iter::once(
-            [self.program.as_ptr() as usize, self.program.len()]
-        ).chain(
-            self.args.iter().map(|arg| [arg.as_ptr() as usize, arg.len()])
-        ).collect();
-
         self.env.apply();
 
         let program = if self.program.contains(':') || self.program.contains('/') {
@@ -321,14 +319,93 @@ impl Command {
             None
         };
 
-        if let Some(program) = program {
-            if let Err(err) = syscall::execve(program.as_os_str().as_bytes(), &args) {
-                io::Error::from_raw_os_error(err.errno as i32)
+        let mut file = if let Some(program) = program {
+            t!(File::open(program.as_os_str()))
+        } else {
+            return io::Error::from_raw_os_error(syscall::ENOENT);
+        };
+
+        // Push all the arguments
+        let mut args: Vec<[usize; 2]> = Vec::with_capacity(1 + self.args.len());
+
+        let interpreter = {
+            let mut reader = BufReader::new(&file);
+
+            let mut shebang = [0; 2];
+            let mut read = 0;
+            loop {
+                match t!(reader.read(&mut shebang[read..])) {
+                    0 => break,
+                    n => read += n,
+                }
+            }
+
+            if &shebang == b"#!" {
+                // This is an interpreted script.
+                // First of all, since we'll be passing another file to
+                // fexec(), we need to manually check that we have permission
+                // to execute this file:
+                let uid = t!(cvt(syscall::getuid()));
+                let gid = t!(cvt(syscall::getgid()));
+                let meta = t!(file.metadata());
+
+                let mode = if uid == meta.uid() as usize {
+                    meta.mode() >> 3*2 & 0o7
+                } else if gid == meta.gid() as usize {
+                    meta.mode() >> 3*1 & 0o7
+                } else {
+                    meta.mode() & 0o7
+                };
+                if mode & 1 == 0 {
+                    return io::Error::from_raw_os_error(syscall::EPERM);
+                }
+
+                // Second of all, we need to actually read which interpreter it wants
+                let mut interpreter = Vec::new();
+                t!(reader.read_until(b'\n', &mut interpreter));
+                // Pop one trailing newline, if any
+                if interpreter.ends_with(&[b'\n']) {
+                    interpreter.pop().unwrap();
+                }
+
+                // FIXME: Here we could just reassign `file` directly, if it
+                // wasn't for lexical lifetimes. Remove the whole `let
+                // interpreter = { ... };` hack once NLL lands.
+                // NOTE: Although DO REMEMBER to make sure the interpreter path
+                // still lives long enough to reach fexec.
+                Some(interpreter)
             } else {
-                panic!("return from exec without err");
+                None
+            }
+        };
+        if let Some(ref interpreter) = interpreter {
+            let path: &OsStr = OsStr::from_bytes(&interpreter);
+            file = t!(File::open(path));
+
+            args.push([interpreter.as_ptr() as usize, interpreter.len()]);
+        } else {
+            t!(file.seek(SeekFrom::Start(0)));
+        }
+
+        args.push([self.program.as_ptr() as usize, self.program.len()]);
+        args.extend(self.args.iter().map(|arg| [arg.as_ptr() as usize, arg.len()]));
+
+        // Push all the variables
+        let mut vars: Vec<[usize; 2]> = Vec::new();
+        {
+            let _guard = ENV_LOCK.lock();
+            let mut environ = *environ();
+            while *environ != ptr::null() {
+                let var = CStr::from_ptr(*environ).to_bytes();
+                vars.push([var.as_ptr() as usize, var.len()]);
+                environ = environ.offset(1);
             }
+        }
+
+        if let Err(err) = syscall::fexec(file.as_raw_fd(), &args, &vars) {
+            io::Error::from_raw_os_error(err.errno as i32)
         } else {
-            io::Error::from_raw_os_error(syscall::ENOENT)
+            panic!("return from exec without err");
         }
     }
 
@@ -392,7 +469,7 @@ impl Stdio {
                 let mut opts = OpenOptions::new();
                 opts.read(readable);
                 opts.write(!readable);
-                let fd = File::open(Path::new("null:"), &opts)?;
+                let fd = SysFile::open(Path::new("null:"), &opts)?;
                 Ok((ChildStdio::Owned(fd.into_fd()), None))
             }
         }
@@ -405,8 +482,8 @@ impl From<AnonPipe> for Stdio {
     }
 }
 
-impl From<File> for Stdio {
-    fn from(file: File) -> Stdio {
+impl From<SysFile> for Stdio {
+    fn from(file: SysFile) -> Stdio {
         Stdio::Fd(file.into_fd())
     }
 }
diff --git a/src/libstd/sys/redox/syscall/call.rs b/src/libstd/sys/redox/syscall/call.rs
index f9a8bd61ac8..577dde4b4be 100644
--- a/src/libstd/sys/redox/syscall/call.rs
+++ b/src/libstd/sys/redox/syscall/call.rs
@@ -45,7 +45,7 @@ pub unsafe fn brk(addr: usize) -> Result<usize> {
 /// # Errors
 ///
 /// * `EACCES` - permission is denied for one of the components of `path`, or `path`
-/// * `EFAULT` - `path` does not point to the process's addressible memory
+/// * `EFAULT` - `path` does not point to the process's addressable memory
 /// * `EIO` - an I/O error occurred
 /// * `ENOENT` - `path` does not exit
 /// * `ENOTDIR` - `path` is not a directory
@@ -82,12 +82,6 @@ pub fn dup2(fd: usize, newfd: usize, buf: &[u8]) -> Result<usize> {
     unsafe { syscall4(SYS_DUP2, fd, newfd, buf.as_ptr() as usize, buf.len()) }
 }
 
-/// Replace the current process with a new executable
-pub fn execve<T: AsRef<[u8]>>(path: T, args: &[[usize; 2]]) -> Result<usize> {
-    unsafe { syscall4(SYS_EXECVE, path.as_ref().as_ptr() as usize,
-                      path.as_ref().len(), args.as_ptr() as usize, args.len()) }
-}
-
 /// Exit the current process
 pub fn exit(status: usize) -> Result<usize> {
     unsafe { syscall1(SYS_EXIT, status) }
@@ -110,9 +104,10 @@ pub fn fcntl(fd: usize, cmd: usize, arg: usize) -> Result<usize> {
     unsafe { syscall3(SYS_FCNTL, fd, cmd, arg) }
 }
 
-/// Register a file for event-based I/O
-pub fn fevent(fd: usize, flags: usize) -> Result<usize> {
-    unsafe { syscall2(SYS_FEVENT, fd, flags) }
+/// Replace the current process with a new executable
+pub fn fexec(fd: usize, args: &[[usize; 2]], vars: &[[usize; 2]]) -> Result<usize> {
+    unsafe { syscall5(SYS_FEXEC, fd, args.as_ptr() as usize, args.len(),
+                      vars.as_ptr() as usize, vars.len()) }
 }
 
 /// Map a file into memory
@@ -347,7 +342,7 @@ pub fn waitpid(pid: usize, status: &mut usize, options: usize) -> Result<usize>
 ///
 /// * `EAGAIN` - the file descriptor was opened with `O_NONBLOCK` and writing would block
 /// * `EBADF` - the file descriptor is not valid or is not open for writing
-/// * `EFAULT` - `buf` does not point to the process's addressible memory
+/// * `EFAULT` - `buf` does not point to the process's addressable memory
 /// * `EIO` - an I/O error occurred
 /// * `ENOSPC` - the device containing the file descriptor has no room for data
 /// * `EPIPE` - the file descriptor refers to a pipe or socket whose reading end is closed
diff --git a/src/libstd/sys/redox/syscall/flag.rs b/src/libstd/sys/redox/syscall/flag.rs
index 0f61b9fa77b..0f1a2c23159 100644
--- a/src/libstd/sys/redox/syscall/flag.rs
+++ b/src/libstd/sys/redox/syscall/flag.rs
@@ -113,4 +113,46 @@ pub const SA_RESTART: usize =   0x10000000;
 pub const SA_NODEFER: usize =   0x40000000;
 pub const SA_RESETHAND: usize = 0x80000000;
 
-pub const WNOHANG: usize = 1;
+pub const WNOHANG: usize =    0x01;
+pub const WUNTRACED: usize =  0x02;
+pub const WCONTINUED: usize = 0x08;
+
+/// True if status indicates the child is stopped.
+pub fn wifstopped(status: usize) -> bool {
+    (status & 0xff) == 0x7f
+}
+
+/// If wifstopped(status), the signal that stopped the child.
+pub fn wstopsig(status: usize) -> usize {
+    (status >> 8) & 0xff
+}
+
+/// True if status indicates the child continued after a stop.
+pub fn wifcontinued(status: usize) -> bool {
+    status == 0xffff
+}
+
+/// True if STATUS indicates termination by a signal.
+pub fn wifsignaled(status: usize) -> bool {
+    ((status & 0x7f) + 1) as i8 >= 2
+}
+
+/// If wifsignaled(status), the terminating signal.
+pub fn wtermsig(status: usize) -> usize {
+    status & 0x7f
+}
+
+/// True if status indicates normal termination.
+pub fn wifexited(status: usize) -> bool {
+    wtermsig(status) == 0
+}
+
+/// If wifexited(status), the exit status.
+pub fn wexitstatus(status: usize) -> usize {
+    (status >> 8) & 0xff
+}
+
+/// True if status indicates a core dump was created.
+pub fn wcoredump(status: usize) -> bool {
+    (status & 0x80) != 0
+}
diff --git a/src/libstd/sys/redox/syscall/number.rs b/src/libstd/sys/redox/syscall/number.rs
index 45cb40e3908..1e187565a67 100644
--- a/src/libstd/sys/redox/syscall/number.rs
+++ b/src/libstd/sys/redox/syscall/number.rs
@@ -36,6 +36,7 @@ pub const SYS_FCHMOD: usize =   SYS_CLASS_FILE | 94;
 pub const SYS_FCHOWN: usize =   SYS_CLASS_FILE | 207;
 pub const SYS_FCNTL: usize =    SYS_CLASS_FILE | 55;
 pub const SYS_FEVENT: usize =   SYS_CLASS_FILE | 927;
+pub const SYS_FEXEC: usize =    SYS_CLASS_FILE | 11;
 pub const SYS_FMAP: usize =     SYS_CLASS_FILE | 90;
 pub const SYS_FUNMAP: usize =   SYS_CLASS_FILE | 91;
 pub const SYS_FPATH: usize =    SYS_CLASS_FILE | SYS_ARG_MSLICE | 928;
@@ -50,7 +51,6 @@ pub const SYS_BRK: usize =      45;
 pub const SYS_CHDIR: usize =    12;
 pub const SYS_CLOCK_GETTIME: usize = 265;
 pub const SYS_CLONE: usize =    120;
-pub const SYS_EXECVE: usize =   11;
 pub const SYS_EXIT: usize =     1;
 pub const SYS_FUTEX: usize =    240;
 pub const SYS_GETCWD: usize =   183;
diff --git a/src/libstd/sys/unix/fd.rs b/src/libstd/sys/unix/fd.rs
index af33d2636fb..5a81d6dfb67 100644
--- a/src/libstd/sys/unix/fd.rs
+++ b/src/libstd/sys/unix/fd.rs
@@ -46,7 +46,7 @@ impl FileDesc {
 
     pub fn raw(&self) -> c_int { self.fd }
 
-    /// Extracts the actual filedescriptor without closing it.
+    /// Extracts the actual file descriptor without closing it.
     pub fn into_raw(self) -> c_int {
         let fd = self.fd;
         mem::forget(self);
diff --git a/src/libstd/sys/unix/rwlock.rs b/src/libstd/sys/unix/rwlock.rs
index c754d5b8359..fcd6f7a27b6 100644
--- a/src/libstd/sys/unix/rwlock.rs
+++ b/src/libstd/sys/unix/rwlock.rs
@@ -14,7 +14,7 @@ use sync::atomic::{AtomicUsize, Ordering};
 
 pub struct RWLock {
     inner: UnsafeCell<libc::pthread_rwlock_t>,
-    write_locked: UnsafeCell<bool>,
+    write_locked: UnsafeCell<bool>, // guarded by the `inner` RwLock
     num_readers: AtomicUsize,
 }
 
@@ -52,13 +52,13 @@ impl RWLock {
         // allow that because it could lead to aliasing issues.
         if r == libc::EAGAIN {
             panic!("rwlock maximum reader count exceeded");
-        } else if r == libc::EDEADLK || *self.write_locked.get() {
+        } else if r == libc::EDEADLK || (r == 0 && *self.write_locked.get()) {
             if r == 0 {
                 self.raw_unlock();
             }
             panic!("rwlock read lock would result in deadlock");
         } else {
-            debug_assert_eq!(r, 0);
+            assert_eq!(r, 0);
             self.num_readers.fetch_add(1, Ordering::Relaxed);
         }
     }
diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs
index a57b8dc7237..8a845efd413 100644
--- a/src/libstd/thread/mod.rs
+++ b/src/libstd/thread/mod.rs
@@ -233,7 +233,7 @@ pub use self::local::{LocalKey, AccessError};
 ///
 /// You may want to use [`spawn`] instead of [`thread::spawn`], when you want
 /// to recover from a failure to launch a thread, indeed the free function will
-/// panick where the `Builder` method will return a [`io::Result`].
+/// panic where the `Builder` method will return a [`io::Result`].
 ///
 /// # Examples
 ///
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 808e19d6f12..227017a9073 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -18,7 +18,6 @@ pub use util::parser::ExprPrecedence;
 use ext::hygiene::{Mark, SyntaxContext};
 use print::pprust;
 use ptr::P;
-use rustc_data_structures::indexed_vec;
 use rustc_data_structures::indexed_vec::Idx;
 #[cfg(target_arch = "x86_64")]
 use rustc_data_structures::static_assert;
@@ -33,7 +32,6 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::Lrc;
 use serialize::{self, Decoder, Encoder};
 use std::fmt;
-use std::u32;
 
 pub use rustc_target::abi::FloatTy;
 
@@ -215,71 +213,54 @@ pub struct ParenthesisedArgs {
     pub output: Option<P<Ty>>,
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
-pub struct NodeId(u32);
-
-impl NodeId {
-    pub fn new(x: usize) -> NodeId {
-        assert!(x < (u32::MAX as usize));
-        NodeId(x as u32)
-    }
-
-    pub fn from_u32(x: u32) -> NodeId {
-        NodeId(x)
-    }
-
-    pub fn as_usize(&self) -> usize {
-        self.0 as usize
+// hack to ensure that we don't try to access the private parts of `NodeId` in this module
+mod node_id_inner {
+    use rustc_data_structures::indexed_vec::Idx;
+    newtype_index! {
+        pub struct NodeId {
+            ENCODABLE = custom
+            DEBUG_FORMAT = "NodeId({})"
+        }
     }
+}
 
-    pub fn as_u32(&self) -> u32 {
-        self.0
-    }
+pub use self::node_id_inner::NodeId;
 
+impl NodeId {
     pub fn placeholder_from_mark(mark: Mark) -> Self {
-        NodeId(mark.as_u32())
+        NodeId::from_u32(mark.as_u32())
     }
 
     pub fn placeholder_to_mark(self) -> Mark {
-        Mark::from_u32(self.0)
+        Mark::from_u32(self.as_u32())
     }
 }
 
 impl fmt::Display for NodeId {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Display::fmt(&self.0, f)
+        fmt::Display::fmt(&self.as_u32(), f)
     }
 }
 
 impl serialize::UseSpecializedEncodable for NodeId {
     fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_u32(self.0)
+        s.emit_u32(self.as_u32())
     }
 }
 
 impl serialize::UseSpecializedDecodable for NodeId {
     fn default_decode<D: Decoder>(d: &mut D) -> Result<NodeId, D::Error> {
-        d.read_u32().map(NodeId)
-    }
-}
-
-impl indexed_vec::Idx for NodeId {
-    fn new(idx: usize) -> Self {
-        NodeId::new(idx)
-    }
-
-    fn index(self) -> usize {
-        self.as_usize()
+        d.read_u32().map(NodeId::from_u32)
     }
 }
 
 /// Node id used to represent the root of the crate.
-pub const CRATE_NODE_ID: NodeId = NodeId(0);
+pub const CRATE_NODE_ID: NodeId = NodeId::from_u32_const(0);
 
 /// When parsing and doing expansions, we initially give all AST nodes this AST
 /// node value. Then later, in the renumber pass, we renumber them to have
 /// small, positive ids.
-pub const DUMMY_NODE_ID: NodeId = NodeId(!0);
+pub const DUMMY_NODE_ID: NodeId = NodeId::MAX;
 
 /// A modifier on a bound, currently this is only used for `?Sized`, where the
 /// modifier is `Maybe`. Negative bounds should also be handled here.
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index e9a6535cba1..9bbd59e09be 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -26,6 +26,7 @@
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_sort_by_cached_key)]
 #![feature(str_escape)]
+#![feature(step_trait)]
 #![feature(try_trait)]
 #![feature(unicode_internals)]
 
@@ -37,7 +38,7 @@ extern crate serialize;
 #[macro_use] extern crate log;
 pub extern crate rustc_errors as errors;
 extern crate syntax_pos;
-extern crate rustc_data_structures;
+#[macro_use] extern crate rustc_data_structures;
 extern crate rustc_target;
 #[macro_use] extern crate scoped_tls;
 #[macro_use]
diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs
index 29bd63d28c5..cfdd4340a19 100644
--- a/src/libsyntax/tokenstream.rs
+++ b/src/libsyntax/tokenstream.rs
@@ -150,7 +150,7 @@ impl TokenTree {
         }
     }
 
-    /// Modify the `TokenTree`'s span inplace.
+    /// Modify the `TokenTree`'s span in-place.
     pub fn set_span(&mut self, span: Span) {
         match *self {
             TokenTree::Token(ref mut sp, _) => *sp = span,
diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs
index dd90ef06c39..2f6b306e8f8 100644
--- a/src/libsyntax_ext/deriving/generic/mod.rs
+++ b/src/libsyntax_ext/deriving/generic/mod.rs
@@ -68,7 +68,7 @@
 //! The `i32`s in `B` and `C0` don't have an identifier, so the
 //! `Option<ident>`s would be `None` for them.
 //!
-//! In the static cases, the structure is summarised, either into the just
+//! In the static cases, the structure is summarized, either into the just
 //! spans of the fields or a list of spans and the field idents (for tuple
 //! structs and record structs, respectively), or a list of these, for
 //! enums (one for each variant). For empty struct and empty enum
diff --git a/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs b/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs
index f2f14f84923..2c5de332327 100644
--- a/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs
+++ b/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs
@@ -43,7 +43,7 @@ fn expand_mbe_matches(cx: &mut ExtCtxt, _: Span, args: &[TokenTree])
                                     &[],
                                     Edition::Edition2015,
                                     // not used...
-                                    NodeId::new(0));
+                                    NodeId::from_u32(0));
     let map = match TokenTree::parse(cx, &mbe_matcher, args.iter().cloned().collect()) {
         Success(map) => map,
         Failure(_, tok) => {
diff --git a/src/test/ui/issues/issue-54348.rs b/src/test/ui/issues/issue-54348.rs
new file mode 100644
index 00000000000..b980290391d
--- /dev/null
+++ b/src/test/ui/issues/issue-54348.rs
@@ -0,0 +1,5 @@
+fn main() {
+    [1][0u64 as usize];
+    [1][1.5 as usize]; // ERROR index out of bounds
+    [1][1u64 as usize]; // ERROR index out of bounds
+}
diff --git a/src/test/ui/issues/issue-54348.stderr b/src/test/ui/issues/issue-54348.stderr
new file mode 100644
index 00000000000..a9f1b494258
--- /dev/null
+++ b/src/test/ui/issues/issue-54348.stderr
@@ -0,0 +1,16 @@
+error: index out of bounds: the len is 1 but the index is 1
+  --> $DIR/issue-54348.rs:3:5
+   |
+LL |     [1][1.5 as usize]; // ERROR index out of bounds
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = note: #[deny(const_err)] on by default
+
+error: index out of bounds: the len is 1 but the index is 1
+  --> $DIR/issue-54348.rs:4:5
+   |
+LL |     [1][1u64 as usize]; // ERROR index out of bounds
+   |     ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/issues/issue-55587.rs b/src/test/ui/issues/issue-55587.rs
new file mode 100644
index 00000000000..8b78749f652
--- /dev/null
+++ b/src/test/ui/issues/issue-55587.rs
@@ -0,0 +1,5 @@
+use std::path::Path;
+
+fn main() {
+    let Path::new(); //~ ERROR expected tuple struct/variant
+}
diff --git a/src/test/ui/issues/issue-55587.stderr b/src/test/ui/issues/issue-55587.stderr
new file mode 100644
index 00000000000..876fb4391b1
--- /dev/null
+++ b/src/test/ui/issues/issue-55587.stderr
@@ -0,0 +1,9 @@
+error[E0164]: expected tuple struct/variant, found method `<Path>::new`
+  --> $DIR/issue-55587.rs:4:9
+   |
+LL |     let Path::new(); //~ ERROR expected tuple struct/variant
+   |         ^^^^^^^^^^^ not a tuple variant or struct
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0164`.
diff --git a/src/test/ui/lint/inclusive-range-pattern-syntax.fixed b/src/test/ui/lint/inclusive-range-pattern-syntax.fixed
index d16859df79e..f0aee8a51f1 100644
--- a/src/test/ui/lint/inclusive-range-pattern-syntax.fixed
+++ b/src/test/ui/lint/inclusive-range-pattern-syntax.fixed
@@ -20,4 +20,10 @@ fn main() {
         //~^ WARN `...` range patterns are deprecated
         _ => {}
     }
+
+    match &despondency {
+        &(1..=2) => {}
+        //~^ WARN `...` range patterns are deprecated
+        _ => {}
+    }
 }
diff --git a/src/test/ui/lint/inclusive-range-pattern-syntax.rs b/src/test/ui/lint/inclusive-range-pattern-syntax.rs
index 9d418aec085..97bc04faa77 100644
--- a/src/test/ui/lint/inclusive-range-pattern-syntax.rs
+++ b/src/test/ui/lint/inclusive-range-pattern-syntax.rs
@@ -20,4 +20,10 @@ fn main() {
         //~^ WARN `...` range patterns are deprecated
         _ => {}
     }
+
+    match &despondency {
+        &1...2 => {}
+        //~^ WARN `...` range patterns are deprecated
+        _ => {}
+    }
 }
diff --git a/src/test/ui/lint/inclusive-range-pattern-syntax.stderr b/src/test/ui/lint/inclusive-range-pattern-syntax.stderr
index de04fed589b..b13afdbc023 100644
--- a/src/test/ui/lint/inclusive-range-pattern-syntax.stderr
+++ b/src/test/ui/lint/inclusive-range-pattern-syntax.stderr
@@ -10,3 +10,9 @@ note: lint level defined here
 LL | #![warn(ellipsis_inclusive_range_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+warning: `...` range patterns are deprecated
+  --> $DIR/inclusive-range-pattern-syntax.rs:25:9
+   |
+LL |         &1...2 => {}
+   |         ^^^^^^ help: use `..=` for an inclusive range: `&(1..=2)`
+
diff --git a/src/test/ui/nll/issue-54382-use-span-of-tail-of-block.nll.stderr b/src/test/ui/nll/issue-54382-use-span-of-tail-of-block.nll.stderr
new file mode 100644
index 00000000000..c308562c0cc
--- /dev/null
+++ b/src/test/ui/nll/issue-54382-use-span-of-tail-of-block.nll.stderr
@@ -0,0 +1,20 @@
+error[E0597]: `_thing1` does not live long enough
+  --> $DIR/issue-54382-use-span-of-tail-of-block.rs:7:29
+   |
+LL |             D("other").next(&_thing1)
+   |             ----------------^^^^^^^^-
+   |             |               |
+   |             |               borrowed value does not live long enough
+   |             a temporary with access to the borrow is created here ...
+LL |         }
+LL |     }
+   |     - `_thing1` dropped here while still borrowed
+LL | 
+LL |     ;
+   |     - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
+   |
+   = note: The temporary is part of an expression at the end of a block. Consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped.
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/issue-54382-use-span-of-tail-of-block.rs b/src/test/ui/nll/issue-54382-use-span-of-tail-of-block.rs
new file mode 100644
index 00000000000..99eafe0e9d1
--- /dev/null
+++ b/src/test/ui/nll/issue-54382-use-span-of-tail-of-block.rs
@@ -0,0 +1,28 @@
+fn main() {
+    {
+        let mut _thing1 = D(Box::new("thing1"));
+        {
+            let _thing2 = D("thing2");
+            side_effects();
+            D("other").next(&_thing1)
+        }
+    }
+
+    ;
+}
+
+#[derive(Debug)]
+struct D<T: std::fmt::Debug>(T);
+
+impl<T: std::fmt::Debug>  Drop for D<T> {
+    fn drop(&mut self) {
+        println!("dropping {:?})", self);
+    }
+}
+
+impl<T: std::fmt::Debug> D<T> {
+    fn next<U: std::fmt::Debug>(&self, _other: U) -> D<U> { D(_other) }
+    fn end(&self) { }
+}
+
+fn side_effects() { }
diff --git a/src/test/ui/nll/issue-54382-use-span-of-tail-of-block.stderr b/src/test/ui/nll/issue-54382-use-span-of-tail-of-block.stderr
new file mode 100644
index 00000000000..eeba7d6bb44
--- /dev/null
+++ b/src/test/ui/nll/issue-54382-use-span-of-tail-of-block.stderr
@@ -0,0 +1,15 @@
+error[E0597]: `_thing1` does not live long enough
+  --> $DIR/issue-54382-use-span-of-tail-of-block.rs:7:30
+   |
+LL |             D("other").next(&_thing1)
+   |                              ^^^^^^^ borrowed value does not live long enough
+LL |         }
+LL |     }
+   |     - `_thing1` dropped here while still borrowed
+LL | 
+LL |     ;
+   |     - borrowed value needs to live until here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/range/range-inclusive-pattern-precedence.stderr b/src/test/ui/range/range-inclusive-pattern-precedence.stderr
index cd5ce3035c6..6fa67a5d4fa 100644
--- a/src/test/ui/range/range-inclusive-pattern-precedence.stderr
+++ b/src/test/ui/range/range-inclusive-pattern-precedence.stderr
@@ -11,10 +11,10 @@ LL |         box 10..=15 => {}
    |             ^^^^^^^ help: add parentheses to clarify the precedence: `(10 ..=15)`
 
 warning: `...` range patterns are deprecated
-  --> $DIR/range-inclusive-pattern-precedence.rs:24:11
+  --> $DIR/range-inclusive-pattern-precedence.rs:24:9
    |
 LL |         &0...9 => {}
-   |           ^^^ help: use `..=` for an inclusive range
+   |         ^^^^^^ help: use `..=` for an inclusive range: `&(0..=9)`
    |
 note: lint level defined here
   --> $DIR/range-inclusive-pattern-precedence.rs:19:9