about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock21
-rw-r--r--src/liballoc/collections/btree/node.rs174
-rw-r--r--src/liballoc/collections/linked_list.rs6
-rw-r--r--src/libcore/fmt/mod.rs9
-rw-r--r--src/libcore/num/mod.rs17
-rw-r--r--src/libcore/ptr.rs2
-rw-r--r--src/libcore/sync/atomic.rs17
-rw-r--r--src/librustc/infer/canonical/query_response.rs51
-rw-r--r--src/librustc/middle/liveness.rs12
-rw-r--r--src/librustc/ty/mod.rs84
-rw-r--r--src/librustc_codegen_llvm/intrinsic.rs3
-rw-r--r--src/librustc_codegen_llvm/llvm_util.rs2
-rw-r--r--src/librustc_mir/borrow_check/mod.rs9
-rw-r--r--src/librustc_mir/borrow_check/nll/invalidation.rs8
-rw-r--r--src/librustc_mir/borrow_check/places_conflict.rs13
-rw-r--r--src/librustc_mir/build/mod.rs7
-rw-r--r--src/librustc_mir/transform/check_unsafety.rs29
-rw-r--r--src/librustc_passes/lib.rs1
-rw-r--r--src/librustc_passes/mir_stats.rs256
-rw-r--r--src/librustc_typeck/check/callee.rs2
-rw-r--r--src/librustc_typeck/check/mod.rs67
-rw-r--r--src/librustdoc/html/static/rustdoc.css2
-rw-r--r--src/librustdoc/test.rs74
-rw-r--r--src/libstd/Cargo.toml1
-rw-r--r--src/libstd/f32.rs3
-rw-r--r--src/libstd/f64.rs3
-rw-r--r--src/libstd/fs.rs2
-rw-r--r--src/libstd/lib.rs1
-rw-r--r--src/libstd/os/raw/mod.rs8
-rw-r--r--src/libstd/sys_common/backtrace.rs239
m---------src/llvm0
-rw-r--r--src/rustllvm/llvm-rebuild-trigger2
-rw-r--r--src/test/rustdoc/comment-in-doctest.rs30
-rw-r--r--src/test/ui/borrowck/borrowck-anon-fields-variant.nll.stderr33
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs4
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr24
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.rs15
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.stderr81
-rw-r--r--src/test/ui/issues/issue-56199.rs23
-rw-r--r--src/test/ui/issues/issue-56199.stderr30
-rw-r--r--src/test/ui/issues/issue-56835.rs10
-rw-r--r--src/test/ui/issues/issue-56835.stderr15
-rw-r--r--src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr1
-rw-r--r--src/test/ui/liveness/liveness-dead.stderr7
-rw-r--r--src/test/ui/liveness/liveness-unused.stderr3
-rw-r--r--src/test/ui/nll/match-on-borrowed.rs8
-rw-r--r--src/test/ui/nll/match-on-borrowed.stderr26
-rw-r--r--src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs6
-rw-r--r--src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr20
-rw-r--r--src/test/ui/suggestions/path-display.rs7
-rw-r--r--src/test/ui/suggestions/path-display.stderr14
-rw-r--r--src/tools/tidy/src/deps.rs1
52 files changed, 648 insertions, 835 deletions
diff --git a/Cargo.lock b/Cargo.lock
index be4a1c2f1d3..7e03474565d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -87,7 +87,7 @@ dependencies = [
  "backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1813,7 +1813,7 @@ name = "rand_chacha"
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1835,7 +1835,7 @@ name = "rand_hc"
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1860,7 +1860,7 @@ name = "rand_xorshift"
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2195,8 +2195,12 @@ dependencies = [
 
 [[package]]
 name = "rustc-demangle"
-version = "0.1.9"
+version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "compiler_builtins 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-std-workspace-core 1.0.0",
+]
 
 [[package]]
 name = "rustc-hash"
@@ -2315,7 +2319,7 @@ dependencies = [
  "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_llvm 0.0.0",
 ]
 
@@ -2331,7 +2335,7 @@ dependencies = [
  "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
- "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_allocator 0.0.0",
  "rustc_apfloat 0.0.0",
  "rustc_codegen_utils 0.0.0",
@@ -2892,6 +2896,7 @@ dependencies = [
  "panic_unwind 0.0.0",
  "profiler_builtins 0.0.0",
  "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_asan 0.0.0",
  "rustc_lsan 0.0.0",
  "rustc_msan 0.0.0",
@@ -3578,7 +3583,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum rustc-ap-serialize 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b2c0e8161e956647592a737074736e6ce05ea36b70c770ea8cca3eb9cb33737"
 "checksum rustc-ap-syntax 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1adc189e5e4500a4167b9afa04e67067f40d0039e0e05870c977bebb561f065a"
 "checksum rustc-ap-syntax_pos 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4d42c430dbb0be4377bfe6aa5099074c63ac8796b24098562c2e2154aecc5652"
-"checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395"
+"checksum rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "82ae957aa1b3055d8e086486723c0ccd3d7b8fa190ae8fa2e35543b6171c810e"
 "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8"
 "checksum rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c6d5a683c6ba4ed37959097e88d71c9e8e26659a3cb5be8b389078e7ad45306"
 "checksum rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40f06724db71e18d68b3b946fdf890ca8c921d9edccc1404fdfdb537b0d12649"
diff --git a/src/liballoc/collections/btree/node.rs b/src/liballoc/collections/btree/node.rs
index 215689dfc48..a2d2d3c74be 100644
--- a/src/liballoc/collections/btree/node.rs
+++ b/src/liballoc/collections/btree/node.rs
@@ -58,9 +58,34 @@ pub const CAPACITY: usize = 2 * B - 1;
 /// these should always be put behind pointers, and specifically behind `BoxedNode` in the owned
 /// case.
 ///
-/// We put the metadata first so that its position is the same for every `K` and `V`, in order
-/// to statically allocate a single dummy node to avoid allocations. This struct is `repr(C)` to
-/// prevent them from being reordered.
+/// We have a separate type for the header and rely on it matching the prefix of `LeafNode`, in
+/// order to statically allocate a single dummy node to avoid allocations. This struct is
+/// `repr(C)` to prevent them from being reordered.  `LeafNode` does not just contain a
+/// `NodeHeader` because we do not want unnecessary padding between `len` and the keys.
+/// Crucially, `NodeHeader` can be safely transmuted to different K and V.  (This is exploited
+/// by `as_header`.)
+/// See `into_key_slice` for an explanation of K2.  K2 cannot be safely transmuted around
+/// because the size of `NodeHeader` depends on its alignment!
+#[repr(C)]
+struct NodeHeader<K, V, K2 = ()> {
+    /// We use `*const` as opposed to `*mut` so as to be covariant in `K` and `V`.
+    /// This either points to an actual node or is null.
+    parent: *const InternalNode<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 non-null.
+    parent_idx: MaybeUninit<u16>,
+
+    /// The number of keys and values this node stores.
+    ///
+    /// This next to `parent_idx` to encourage the compiler to join `len` and
+    /// `parent_idx` into the same 32-bit word, reducing space overhead.
+    len: u16,
+
+    /// See `into_key_slice`.
+    keys_start: [K2; 0],
+}
 #[repr(C)]
 struct LeafNode<K, V> {
     /// We use `*const` as opposed to `*mut` so as to be covariant in `K` and `V`.
@@ -98,24 +123,25 @@ impl<K, V> LeafNode<K, V> {
             len: 0
         }
     }
+}
 
+impl<K, V> NodeHeader<K, V> {
     fn is_shared_root(&self) -> bool {
         ptr::eq(self, &EMPTY_ROOT_NODE as *const _ as *const _)
     }
 }
 
 // We need to implement Sync here in order to make a static instance.
-unsafe impl Sync for LeafNode<(), ()> {}
+unsafe impl Sync for NodeHeader<(), ()> {}
 
 // An empty node used as a placeholder for the root node, to avoid allocations.
-// We use () in order to save space, since no operation on an empty tree will
+// We use just a header in order to save space, since no operation on an empty tree will
 // ever take a pointer past the first key.
-static EMPTY_ROOT_NODE: LeafNode<(), ()> = LeafNode {
+static EMPTY_ROOT_NODE: NodeHeader<(), ()> = NodeHeader {
     parent: ptr::null(),
     parent_idx: MaybeUninit::uninitialized(),
     len: 0,
-    keys: MaybeUninit::uninitialized(),
-    vals: MaybeUninit::uninitialized(),
+    keys_start: [],
 };
 
 /// The underlying representation of internal nodes. As with `LeafNode`s, these should be hidden
@@ -281,7 +307,7 @@ impl<K, V> Root<K, V> {
                                     .node)
         };
         self.height -= 1;
-        self.as_mut().as_leaf_mut().parent = ptr::null();
+        unsafe { (*self.as_mut().as_leaf_mut()).parent = ptr::null(); }
 
         unsafe {
             Global.dealloc(NonNull::from(top).cast(), Layout::new::<InternalNode<K, V>>());
@@ -306,6 +332,11 @@ impl<K, V> Root<K, V> {
 ///   `Leaf`, the `NodeRef` points to a leaf node, when this is `Internal` the
 ///   `NodeRef` points to an internal node, and when this is `LeafOrInternal` the
 ///   `NodeRef` could be pointing to either type of node.
+///   Note that in case of a leaf node, this might still be the shared root!  Only turn
+///   this into a `LeafNode` reference if you know it is not a root!  Shared references
+///   must be dereferencable *for the entire size of their pointee*, so `&InternalNode`
+///   pointing to the shared root is UB.
+///   Turning this into a `NodeHeader` is always safe.
 pub struct NodeRef<BorrowType, K, V, Type> {
     height: usize,
     node: NonNull<LeafNode<K, V>>,
@@ -352,7 +383,7 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
     /// Finds the length of the node. This is the number of keys or values. In an
     /// internal node, the number of edges is `len() + 1`.
     pub fn len(&self) -> usize {
-        self.as_leaf().len as usize
+        self.as_header().len as usize
     }
 
     /// Returns the height of this node in the whole tree. Zero height denotes the
@@ -382,14 +413,19 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
         }
     }
 
-    fn as_leaf(&self) -> &LeafNode<K, V> {
+    /// Assert that this is indeed a proper leaf node, and not the shared root.
+    unsafe fn as_leaf(&self) -> &LeafNode<K, V> {
+        self.node.as_ref()
+    }
+
+    fn as_header(&self) -> &NodeHeader<K, V> {
         unsafe {
-            self.node.as_ref()
+            &*(self.node.as_ptr() as *const NodeHeader<K, V>)
         }
     }
 
     pub fn is_shared_root(&self) -> bool {
-        self.as_leaf().is_shared_root()
+        self.as_header().is_shared_root()
     }
 
     pub fn keys(&self) -> &[K] {
@@ -418,7 +454,7 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
         >,
         Self
     > {
-        let parent_as_leaf = self.as_leaf().parent as *const LeafNode<K, V>;
+        let parent_as_leaf = self.as_header().parent as *const LeafNode<K, V>;
         if let Some(non_zero) = NonNull::new(parent_as_leaf as *mut _) {
             Ok(Handle {
                 node: NodeRef {
@@ -427,7 +463,7 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
                     root: self.root,
                     _marker: PhantomData
                 },
-                idx: unsafe { usize::from(*self.as_leaf().parent_idx.get_ref()) },
+                idx: unsafe { usize::from(*self.as_header().parent_idx.get_ref()) },
                 _marker: PhantomData
             })
         } else {
@@ -534,10 +570,10 @@ impl<'a, K, V, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
         }
     }
 
-    fn as_leaf_mut(&mut self) -> &mut LeafNode<K, V> {
-        unsafe {
-            self.node.as_mut()
-        }
+    /// Returns a raw ptr to avoid asserting exclusive access to the entire node.
+    fn as_leaf_mut(&mut self) -> *mut LeafNode<K, V> {
+        // We are mutable, so we cannot be the root, so accessing this as a leaf is okay.
+        self.node.as_ptr()
     }
 
     fn keys_mut(&mut self) -> &mut [K] {
@@ -551,28 +587,50 @@ impl<'a, K, V, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
 
 impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Immut<'a>, K, V, Type> {
     fn into_key_slice(self) -> &'a [K] {
-        // When taking a pointer to the keys, if our key has a stricter
-        // alignment requirement than the shared root does, then the pointer
-        // would be out of bounds, which LLVM assumes will not happen. If the
-        // alignment is more strict, we need to make an empty slice that doesn't
-        // use an out of bounds pointer.
+        // We have to be careful here because we might be pointing to the shared root.
+        // In that case, we must not create an `&LeafNode`.  We could just return
+        // an empty slice whenever the length is 0 (this includes the shared root),
+        // but we want to avoid that run-time check.
+        // Instead, we create a slice pointing into the node whenever possible.
+        // We can sometimes do this even for the shared root, as the slice will be
+        // empty.  We cannot *always* do this because if the type is too highly
+        // aligned, the offset of `keys` in a "full node" might be outside the bounds
+        // of the header!  So we do an alignment check first, that will be
+        // evaluated at compile-time, and only do any run-time check in the rare case
+        // that the alignment is very big.
         if mem::align_of::<K>() > mem::align_of::<LeafNode<(), ()>>() && self.is_shared_root() {
             &[]
         } else {
-            // Here either it's not the root, or the alignment is less strict,
-            // in which case the keys pointer will point "one-past-the-end" of
-            // the node, which is allowed by LLVM.
+            // Thanks to the alignment check above, we know that `keys` will be
+            // in-bounds of some allocation even if this is the shared root!
+            // (We might be one-past-the-end, but that is allowed by LLVM.)
+            // Getting the pointer is tricky though.  `NodeHeader` does not have a `keys`
+            // field because we want its size to not depend on the alignment of `K`
+            // (needed becuase `as_header` should be safe).  We cannot call `as_leaf`
+            // because we might be the shared root.
+            // For this reason, `NodeHeader` has this `K2` parameter (that's usually `()`
+            // and hence just adds a size-0-align-1 field, not affecting layout).
+            // We know that we can transmute `NodeHeader<K, V, ()>` to `NodeHeader<K, V, K>`
+            // because we did the alignment check above, and hence `NodeHeader<K, V, K>`
+            // is not bigger than `NodeHeader<K, V, ()>`!  Then we can use `NodeHeader<K, V, K>`
+            // to compute the pointer where the keys start.
+            // This entire hack will become unnecessary once
+            // <https://github.com/rust-lang/rfcs/pull/2582> lands, then we can just take a raw
+            // pointer to the `keys` field of `*const InternalNode<K, V>`.
+
+            // This is a non-debug-assert because it can be completely compile-time evaluated.
+            assert!(mem::size_of::<NodeHeader<K, V>>() == mem::size_of::<NodeHeader<K, V, K>>());
+            let header = self.as_header() as *const _ as *const NodeHeader<K, V, K>;
+            let keys = unsafe { &(*header).keys_start as *const _ as *const K };
             unsafe {
-                slice::from_raw_parts(
-                    self.as_leaf().keys.as_ptr() as *const K,
-                    self.len()
-                )
+                slice::from_raw_parts(keys, self.len())
             }
         }
     }
 
     fn into_val_slice(self) -> &'a [V] {
         debug_assert!(!self.is_shared_root());
+        // We cannot be the root, so `as_leaf` is okay
         unsafe {
             slice::from_raw_parts(
                 self.as_leaf().vals.as_ptr() as *const V,
@@ -602,7 +660,7 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
         } else {
             unsafe {
                 slice::from_raw_parts_mut(
-                    self.as_leaf_mut().keys.as_mut_ptr() as *mut K,
+                    (*self.as_leaf_mut()).keys.as_mut_ptr() as *mut K,
                     self.len()
                 )
             }
@@ -613,7 +671,7 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
         debug_assert!(!self.is_shared_root());
         unsafe {
             slice::from_raw_parts_mut(
-                self.as_leaf_mut().vals.as_mut_ptr() as *mut V,
+                (*self.as_leaf_mut()).vals.as_mut_ptr() as *mut V,
                 self.len()
             )
         }
@@ -637,9 +695,9 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Leaf> {
         unsafe {
             ptr::write(self.keys_mut().get_unchecked_mut(idx), key);
             ptr::write(self.vals_mut().get_unchecked_mut(idx), val);
-        }
 
-        self.as_leaf_mut().len += 1;
+            (*self.as_leaf_mut()).len += 1;
+        }
     }
 
     /// Adds a key/value pair to the beginning of the node.
@@ -651,9 +709,9 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Leaf> {
         unsafe {
             slice_insert(self.keys_mut(), 0, key);
             slice_insert(self.vals_mut(), 0, val);
-        }
 
-        self.as_leaf_mut().len += 1;
+            (*self.as_leaf_mut()).len += 1;
+        }
     }
 }
 
@@ -672,7 +730,7 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
             ptr::write(self.vals_mut().get_unchecked_mut(idx), val);
             ptr::write(self.as_internal_mut().edges.get_unchecked_mut(idx + 1), edge.node);
 
-            self.as_leaf_mut().len += 1;
+            (*self.as_leaf_mut()).len += 1;
 
             Handle::new_edge(self.reborrow_mut(), idx + 1).correct_parent_link();
         }
@@ -708,7 +766,7 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
                 edge.node
             );
 
-            self.as_leaf_mut().len += 1;
+            (*self.as_leaf_mut()).len += 1;
 
             self.correct_all_childrens_parent_links();
         }
@@ -732,12 +790,12 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal> {
                 ForceResult::Internal(internal) => {
                     let edge = ptr::read(internal.as_internal().edges.get_unchecked(idx + 1));
                     let mut new_root = Root { node: edge, height: internal.height - 1 };
-                    new_root.as_mut().as_leaf_mut().parent = ptr::null();
+                    (*new_root.as_mut().as_leaf_mut()).parent = ptr::null();
                     Some(new_root)
                 }
             };
 
-            self.as_leaf_mut().len -= 1;
+            (*self.as_leaf_mut()).len -= 1;
             (key, val, edge)
         }
     }
@@ -765,7 +823,7 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal> {
                     );
 
                     let mut new_root = Root { node: edge, height: internal.height - 1 };
-                    new_root.as_mut().as_leaf_mut().parent = ptr::null();
+                    (*new_root.as_mut().as_leaf_mut()).parent = ptr::null();
 
                     for i in 0..old_len {
                         Handle::new_edge(internal.reborrow_mut(), i).correct_parent_link();
@@ -775,7 +833,7 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal> {
                 }
             };
 
-            self.as_leaf_mut().len -= 1;
+            (*self.as_leaf_mut()).len -= 1;
 
             (key, val, edge)
         }
@@ -966,7 +1024,7 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge
             slice_insert(self.node.keys_mut(), self.idx, key);
             slice_insert(self.node.vals_mut(), self.idx, val);
 
-            self.node.as_leaf_mut().len += 1;
+            (*self.node.as_leaf_mut()).len += 1;
 
             self.node.vals_mut().get_unchecked_mut(self.idx)
         }
@@ -1009,8 +1067,10 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
         let idx = self.idx as u16;
         let ptr = self.node.as_internal_mut() as *mut _;
         let mut child = self.descend();
-        child.as_leaf_mut().parent = ptr;
-        child.as_leaf_mut().parent_idx.set(idx);
+        unsafe {
+            (*child.as_leaf_mut()).parent = ptr;
+            (*child.as_leaf_mut()).parent_idx.set(idx);
+        }
     }
 
     /// Unsafely asserts to the compiler some static information about whether the underlying
@@ -1158,7 +1218,7 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::KV>
                 new_len
             );
 
-            self.node.as_leaf_mut().len = self.idx as u16;
+            (*self.node.as_leaf_mut()).len = self.idx as u16;
             new_node.len = new_len as u16;
 
             (
@@ -1180,7 +1240,7 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::KV>
         unsafe {
             let k = slice_remove(self.node.keys_mut(), self.idx);
             let v = slice_remove(self.node.vals_mut(), self.idx);
-            self.node.as_leaf_mut().len -= 1;
+            (*self.node.as_leaf_mut()).len -= 1;
             (self.left_edge(), k, v)
         }
     }
@@ -1221,7 +1281,7 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
                 new_len + 1
             );
 
-            self.node.as_leaf_mut().len = self.idx as u16;
+            (*self.node.as_leaf_mut()).len = self.idx as u16;
             new_node.data.len = new_len as u16;
 
             let mut new_root = Root {
@@ -1295,9 +1355,9 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
             for i in self.idx+1..self.node.len() {
                 Handle::new_edge(self.node.reborrow_mut(), i).correct_parent_link();
             }
-            self.node.as_leaf_mut().len -= 1;
+            (*self.node.as_leaf_mut()).len -= 1;
 
-            left_node.as_leaf_mut().len += right_len as u16 + 1;
+            (*left_node.as_leaf_mut()).len += right_len as u16 + 1;
 
             if self.node.height > 1 {
                 ptr::copy_nonoverlapping(
@@ -1407,8 +1467,8 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
                 move_kv(left_kv, new_left_len, parent_kv, 0, 1);
             }
 
-            left_node.reborrow_mut().as_leaf_mut().len -= count as u16;
-            right_node.reborrow_mut().as_leaf_mut().len += count as u16;
+            (*left_node.reborrow_mut().as_leaf_mut()).len -= count as u16;
+            (*right_node.reborrow_mut().as_leaf_mut()).len += count as u16;
 
             match (left_node.force(), right_node.force()) {
                 (ForceResult::Internal(left), ForceResult::Internal(mut right)) => {
@@ -1468,8 +1528,8 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
                           new_right_len);
             }
 
-            left_node.reborrow_mut().as_leaf_mut().len += count as u16;
-            right_node.reborrow_mut().as_leaf_mut().len -= count as u16;
+            (*left_node.reborrow_mut().as_leaf_mut()).len += count as u16;
+            (*right_node.reborrow_mut().as_leaf_mut()).len -= count as u16;
 
             match (left_node.force(), right_node.force()) {
                 (ForceResult::Internal(left), ForceResult::Internal(mut right)) => {
@@ -1560,8 +1620,8 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>, ma
 
             move_kv(left_kv, left_new_len, right_kv, 0, right_new_len);
 
-            left_node.reborrow_mut().as_leaf_mut().len = left_new_len as u16;
-            right_node.reborrow_mut().as_leaf_mut().len = right_new_len as u16;
+            (*left_node.reborrow_mut().as_leaf_mut()).len = left_new_len as u16;
+            (*right_node.reborrow_mut().as_leaf_mut()).len = right_new_len as u16;
 
             match (left_node.force(), right_node.force()) {
                 (ForceResult::Internal(left), ForceResult::Internal(right)) => {
diff --git a/src/liballoc/collections/linked_list.rs b/src/liballoc/collections/linked_list.rs
index 2ef84dbade0..ba46fafaf16 100644
--- a/src/liballoc/collections/linked_list.rs
+++ b/src/liballoc/collections/linked_list.rs
@@ -627,7 +627,9 @@ impl<T> LinkedList<T> {
         self.pop_front_node().map(Node::into_element)
     }
 
-    /// Appends an element to the back of a list
+    /// Appends an element to the back of a list.
+    ///
+    /// This operation should compute in O(1) time.
     ///
     /// # Examples
     ///
@@ -647,6 +649,8 @@ impl<T> LinkedList<T> {
     /// Removes the last element from a list and returns it, or `None` if
     /// it is empty.
     ///
+    /// This operation should compute in O(1) time.
+    ///
     /// # Examples
     ///
     /// ```
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index 0c5256b981e..8e0caa5ae33 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -609,10 +609,15 @@ pub trait Debug {
 /// println!("The origin is: {}", origin);
 /// ```
 #[rustc_on_unimplemented(
+    on(
+        _Self="std::path::Path",
+        label="`{Self}` cannot be formatted with the default formatter; call `.display()` on it",
+        note="call `.display()` or `.to_string_lossy()` to safely print paths, \
+              as they may contain non-Unicode data"
+    ),
     message="`{Self}` doesn't implement `{Display}`",
     label="`{Self}` cannot be formatted with the default formatter",
-    note="in format strings you may be able to use `{{:?}}` \
-          (or {{:#?}} for pretty-print) instead",
+    note="in format strings you may be able to use `{{:?}}` (or {{:#?}} for pretty-print) instead",
 )]
 #[doc(alias = "{}")]
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 4acf3a15ebf..f1df1f2856e 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -70,7 +70,7 @@ assert_eq!(size_of::<Option<std::num::", stringify!($Ty), ">>(), size_of::<", st
                 #[stable(feature = "nonzero", since = "1.28.0")]
                 #[inline]
                 pub const unsafe fn new_unchecked(n: $Int) -> Self {
-                    $Ty(unsafe { NonZero(n) })
+                    $Ty(NonZero(n))
                 }
 
                 /// Create a non-zero if the given value is not zero.
@@ -2150,19 +2150,6 @@ impl isize {
          "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]" }
 }
 
-// Emits the correct `cttz` call, depending on the size of the type.
-macro_rules! uint_cttz_call {
-    // As of LLVM 3.6 the codegen for the zero-safe cttz8 intrinsic
-    // emits two conditional moves on x86_64. By promoting the value to
-    // u16 and setting bit 8, we get better code without any conditional
-    // operations.
-    // FIXME: There's a LLVM patch (http://reviews.llvm.org/D9284)
-    // pending, remove this workaround once LLVM generates better code
-    // for cttz8.
-    ($value:expr, 8) => { intrinsics::cttz($value as u16 | 0x100) };
-    ($value:expr, $_BITS:expr) => { intrinsics::cttz($value) }
-}
-
 // `Int` + `UnsignedInt` implemented for unsigned integers
 macro_rules! uint_impl {
     ($SelfT:ty, $ActualT:ty, $BITS:expr, $MaxV:expr, $Feature:expr, $EndFeature:expr,
@@ -2306,7 +2293,7 @@ assert_eq!(n.trailing_zeros(), 3);", $EndFeature, "
             #[rustc_const_unstable(feature = "const_int_ops")]
             #[inline]
             pub const fn trailing_zeros(self) -> u32 {
-                unsafe { uint_cttz_call!(self, $BITS) as u32 }
+                unsafe { intrinsics::cttz(self) as u32 }
             }
         }
 
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index 79ca600b4a5..b3c93ae1fa7 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -2928,7 +2928,7 @@ impl<T: ?Sized> NonNull<T> {
     #[stable(feature = "nonnull", since = "1.25.0")]
     #[inline]
     pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
-        NonNull { pointer: unsafe { NonZero(ptr as _) } }
+        NonNull { pointer: NonZero(ptr as _) }
     }
 
     /// Creates a new `NonNull` if `ptr` is non-null.
diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs
index 060983a702f..d2683e31eef 100644
--- a/src/libcore/sync/atomic.rs
+++ b/src/libcore/sync/atomic.rs
@@ -1072,6 +1072,15 @@ impl<T> AtomicPtr<T> {
 #[cfg(target_has_atomic = "8")]
 #[stable(feature = "atomic_bool_from", since = "1.24.0")]
 impl From<bool> for AtomicBool {
+    /// Converts a `bool` into an `AtomicBool`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::sync::atomic::AtomicBool;
+    /// let atomic_bool = AtomicBool::from(true);
+    /// assert_eq!(format!("{:?}", atomic_bool), "true")
+    /// ```
     #[inline]
     fn from(b: bool) -> Self { Self::new(b) }
 }
@@ -1126,8 +1135,12 @@ macro_rules! atomic_int {
 
         #[$stable_from]
         impl From<$int_type> for $atomic_type {
-            #[inline]
-            fn from(v: $int_type) -> Self { Self::new(v) }
+            doc_comment! {
+                concat!(
+"Converts an `", stringify!($int_type), "` into an `", stringify!($atomic_type), "`."),
+                #[inline]
+                fn from(v: $int_type) -> Self { Self::new(v) }
+            }
         }
 
         #[$stable_debug]
diff --git a/src/librustc/infer/canonical/query_response.rs b/src/librustc/infer/canonical/query_response.rs
index 8d2b1d74c55..43bc9d88895 100644
--- a/src/librustc/infer/canonical/query_response.rs
+++ b/src/librustc/infer/canonical/query_response.rs
@@ -36,6 +36,7 @@ use traits::{Obligation, ObligationCause, PredicateObligation};
 use ty::fold::TypeFoldable;
 use ty::subst::{Kind, UnpackedKind};
 use ty::{self, BoundVar, Lift, Ty, TyCtxt};
+use util::captures::Captures;
 
 impl<'cx, 'gcx, 'tcx> InferCtxtBuilder<'cx, 'gcx, 'tcx> {
     /// The "main method" for a canonicalized trait query. Given the
@@ -527,32 +528,30 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
         param_env: ty::ParamEnv<'tcx>,
         unsubstituted_region_constraints: &'a [QueryRegionConstraint<'tcx>],
         result_subst: &'a CanonicalVarValues<'tcx>,
-    ) -> impl Iterator<Item = PredicateObligation<'tcx>> + 'a {
-        Box::new(
-            unsubstituted_region_constraints
-                .iter()
-                .map(move |constraint| {
-                    let constraint = substitute_value(self.tcx, result_subst, constraint);
-                    let &ty::OutlivesPredicate(k1, r2) = constraint.skip_binder(); // restored below
-
-                    Obligation::new(
-                        cause.clone(),
-                        param_env,
-                        match k1.unpack() {
-                            UnpackedKind::Lifetime(r1) => ty::Predicate::RegionOutlives(
-                                ty::Binder::bind(
-                                    ty::OutlivesPredicate(r1, r2)
-                                )
-                            ),
-                            UnpackedKind::Type(t1) => ty::Predicate::TypeOutlives(
-                                ty::Binder::bind(
-                                    ty::OutlivesPredicate(t1, r2)
-                                )
-                            ),
-                        }
-                    )
-                })
-        ) as Box<dyn Iterator<Item = _>>
+    ) -> impl Iterator<Item = PredicateObligation<'tcx>> + 'a + Captures<'gcx> {
+        unsubstituted_region_constraints
+            .iter()
+            .map(move |constraint| {
+                let constraint = substitute_value(self.tcx, result_subst, constraint);
+                let &ty::OutlivesPredicate(k1, r2) = constraint.skip_binder(); // restored below
+
+                Obligation::new(
+                    cause.clone(),
+                    param_env,
+                    match k1.unpack() {
+                        UnpackedKind::Lifetime(r1) => ty::Predicate::RegionOutlives(
+                            ty::Binder::bind(
+                                ty::OutlivesPredicate(r1, r2)
+                            )
+                        ),
+                        UnpackedKind::Type(t1) => ty::Predicate::TypeOutlives(
+                            ty::Binder::bind(
+                                ty::OutlivesPredicate(t1, r2)
+                            )
+                        ),
+                    }
+                )
+            })
     }
 
     /// Given two sets of values for the same set of canonical variables, unify them.
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index e576951417f..31a75bd106e 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -1657,11 +1657,15 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
     fn report_dead_assign(&self, hir_id: HirId, sp: Span, var: Variable, is_argument: bool) {
         if let Some(name) = self.should_warn(var) {
             if is_argument {
-                self.ir.tcx.lint_hir(lint::builtin::UNUSED_ASSIGNMENTS, hir_id, sp,
-                    &format!("value passed to `{}` is never read", name));
+                self.ir.tcx.struct_span_lint_hir(lint::builtin::UNUSED_ASSIGNMENTS, hir_id, sp,
+                &format!("value passed to `{}` is never read", name))
+                .help("maybe it is overwritten before being read?")
+                .emit();
             } else {
-                self.ir.tcx.lint_hir(lint::builtin::UNUSED_ASSIGNMENTS, hir_id, sp,
-                    &format!("value assigned to `{}` is never read", name));
+                self.ir.tcx.struct_span_lint_hir(lint::builtin::UNUSED_ASSIGNMENTS, hir_id, sp,
+                &format!("value assigned to `{}` is never read", name))
+                .help("maybe it is overwritten before being read?")
+                .emit();
             }
         }
     }
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index a1fc949137d..429b7f03af8 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -1754,17 +1754,19 @@ bitflags! {
     pub struct AdtFlags: u32 {
         const NO_ADT_FLAGS        = 0;
         const IS_ENUM             = 1 << 0;
-        const IS_PHANTOM_DATA     = 1 << 1;
-        const IS_FUNDAMENTAL      = 1 << 2;
-        const IS_UNION            = 1 << 3;
-        const IS_BOX              = 1 << 4;
+        const IS_UNION            = 1 << 1;
+        const IS_STRUCT           = 1 << 2;
+        const HAS_CTOR            = 1 << 3;
+        const IS_PHANTOM_DATA     = 1 << 4;
+        const IS_FUNDAMENTAL      = 1 << 5;
+        const IS_BOX              = 1 << 6;
         /// Indicates whether the type is an `Arc`.
-        const IS_ARC              = 1 << 5;
+        const IS_ARC              = 1 << 7;
         /// Indicates whether the type is an `Rc`.
-        const IS_RC               = 1 << 6;
+        const IS_RC               = 1 << 8;
         /// Indicates whether the variant list of this ADT is `#[non_exhaustive]`.
         /// (i.e., this flag is never set unless this ADT is an enum).
-        const IS_VARIANT_LIST_NON_EXHAUSTIVE   = 1 << 7;
+        const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 9;
     }
 }
 
@@ -2079,31 +2081,43 @@ impl<'a, 'gcx, 'tcx> AdtDef {
            repr: ReprOptions) -> Self {
         debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr);
         let mut flags = AdtFlags::NO_ADT_FLAGS;
+
+        if kind == AdtKind::Enum && tcx.has_attr(did, "non_exhaustive") {
+            debug!("found non-exhaustive variant list for {:?}", did);
+            flags = flags | AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE;
+        }
+        flags |= match kind {
+            AdtKind::Enum => AdtFlags::IS_ENUM,
+            AdtKind::Union => AdtFlags::IS_UNION,
+            AdtKind::Struct => AdtFlags::IS_STRUCT,
+        };
+
+        if let AdtKind::Struct = kind {
+            let variant_def = &variants[VariantIdx::new(0)];
+            let def_key = tcx.def_key(variant_def.did);
+            match def_key.disambiguated_data.data {
+                DefPathData::StructCtor => flags |= AdtFlags::HAS_CTOR,
+                _ => (),
+            }
+        }
+
         let attrs = tcx.get_attrs(did);
         if attr::contains_name(&attrs, "fundamental") {
-            flags = flags | AdtFlags::IS_FUNDAMENTAL;
+            flags |= AdtFlags::IS_FUNDAMENTAL;
         }
         if Some(did) == tcx.lang_items().phantom_data() {
-            flags = flags | AdtFlags::IS_PHANTOM_DATA;
+            flags |= AdtFlags::IS_PHANTOM_DATA;
         }
         if Some(did) == tcx.lang_items().owned_box() {
-            flags = flags | AdtFlags::IS_BOX;
+            flags |= AdtFlags::IS_BOX;
         }
         if Some(did) == tcx.lang_items().arc() {
-            flags = flags | AdtFlags::IS_ARC;
+            flags |= AdtFlags::IS_ARC;
         }
         if Some(did) == tcx.lang_items().rc() {
-            flags = flags | AdtFlags::IS_RC;
-        }
-        if kind == AdtKind::Enum && tcx.has_attr(did, "non_exhaustive") {
-            debug!("found non-exhaustive variant list for {:?}", did);
-            flags = flags | AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE;
-        }
-        match kind {
-            AdtKind::Enum => flags = flags | AdtFlags::IS_ENUM,
-            AdtKind::Union => flags = flags | AdtFlags::IS_UNION,
-            AdtKind::Struct => {}
+            flags |= AdtFlags::IS_RC;
         }
+
         AdtDef {
             did,
             variants,
@@ -2114,25 +2128,25 @@ impl<'a, 'gcx, 'tcx> AdtDef {
 
     #[inline]
     pub fn is_struct(&self) -> bool {
-        !self.is_union() && !self.is_enum()
+        self.flags.contains(AdtFlags::IS_STRUCT)
     }
 
     #[inline]
     pub fn is_union(&self) -> bool {
-        self.flags.intersects(AdtFlags::IS_UNION)
+        self.flags.contains(AdtFlags::IS_UNION)
     }
 
     #[inline]
     pub fn is_enum(&self) -> bool {
-        self.flags.intersects(AdtFlags::IS_ENUM)
+        self.flags.contains(AdtFlags::IS_ENUM)
     }
 
     #[inline]
     pub fn is_variant_list_non_exhaustive(&self) -> bool {
-        self.flags.intersects(AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE)
+        self.flags.contains(AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE)
     }
 
-    /// Returns the kind of the ADT - Struct or Enum.
+    /// Returns the kind of the ADT.
     #[inline]
     pub fn adt_kind(&self) -> AdtKind {
         if self.is_enum() {
@@ -2161,33 +2175,39 @@ impl<'a, 'gcx, 'tcx> AdtDef {
         }
     }
 
-    /// Returns whether this type is #[fundamental] for the purposes
+    /// If this function returns `true`, it implies that `is_struct` must return `true`.
+    #[inline]
+    pub fn has_ctor(&self) -> bool {
+        self.flags.contains(AdtFlags::HAS_CTOR)
+    }
+
+    /// Returns whether this type is `#[fundamental]` for the purposes
     /// of coherence checking.
     #[inline]
     pub fn is_fundamental(&self) -> bool {
-        self.flags.intersects(AdtFlags::IS_FUNDAMENTAL)
+        self.flags.contains(AdtFlags::IS_FUNDAMENTAL)
     }
 
     /// Returns `true` if this is PhantomData<T>.
     #[inline]
     pub fn is_phantom_data(&self) -> bool {
-        self.flags.intersects(AdtFlags::IS_PHANTOM_DATA)
+        self.flags.contains(AdtFlags::IS_PHANTOM_DATA)
     }
 
     /// Returns `true` if this is `Arc<T>`.
     pub fn is_arc(&self) -> bool {
-        self.flags.intersects(AdtFlags::IS_ARC)
+        self.flags.contains(AdtFlags::IS_ARC)
     }
 
     /// Returns `true` if this is `Rc<T>`.
     pub fn is_rc(&self) -> bool {
-        self.flags.intersects(AdtFlags::IS_RC)
+        self.flags.contains(AdtFlags::IS_RC)
     }
 
     /// Returns `true` if this is Box<T>.
     #[inline]
     pub fn is_box(&self) -> bool {
-        self.flags.intersects(AdtFlags::IS_BOX)
+        self.flags.contains(AdtFlags::IS_BOX)
     }
 
     /// Returns whether this type has a destructor.
diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs
index 8b26ada1576..e229f8d95cd 100644
--- a/src/librustc_codegen_llvm/intrinsic.rs
+++ b/src/librustc_codegen_llvm/intrinsic.rs
@@ -1192,7 +1192,7 @@ fn generic_simd_intrinsic(
         return Ok(bx.select(m_i1s, args[1].immediate(), args[2].immediate()));
     }
 
-    // every intrinsic takes a SIMD vector as its first argument
+    // every intrinsic below takes a SIMD vector as its first argument
     require_simd!(arg_tys[0], "input");
     let in_ty = arg_tys[0];
     let in_elem = arg_tys[0].simd_type(tcx);
@@ -1296,6 +1296,7 @@ fn generic_simd_intrinsic(
     if name == "simd_select" {
         let m_elem_ty = in_elem;
         let m_len = in_len;
+        require_simd!(arg_tys[1], "argument");
         let v_len = arg_tys[1].simd_size(tcx);
         require!(m_len == v_len,
                  "mismatched lengths: mask length `{}` != other vector length `{}`",
diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs
index 12109ae1662..82b1d7e8b40 100644
--- a/src/librustc_codegen_llvm/llvm_util.rs
+++ b/src/librustc_codegen_llvm/llvm_util.rs
@@ -140,6 +140,7 @@ const X86_WHITELIST: &[(&str, Option<&str>)] = &[
     ("avx512vpopcntdq", Some("avx512_target_feature")),
     ("bmi1", None),
     ("bmi2", None),
+    ("cmpxchg16b", Some("cmpxchg16b_target_feature")),
     ("fma", None),
     ("fxsr", None),
     ("lzcnt", None),
@@ -212,6 +213,7 @@ pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str {
         ("x86", "pclmulqdq") => "pclmul",
         ("x86", "rdrand") => "rdrnd",
         ("x86", "bmi1") => "bmi",
+        ("x86", "cmpxchg16b") => "cx16",
         ("aarch64", "fp") => "fp-armv8",
         ("aarch64", "fp16") => "fullfp16",
         (_, s) => s,
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index e3029c6a19d..5eca62938f7 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -545,7 +545,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
                 self.mutate_place(
                     ContextKind::SetDiscrim.new(location),
                     (place, span),
-                    Shallow(Some(ArtificialField::Discriminant)),
+                    Shallow(None),
                     JustWrite,
                     flow_state,
                 );
@@ -782,7 +782,6 @@ use self::AccessDepth::{Deep, Shallow};
 
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 enum ArtificialField {
-    Discriminant,
     ArrayLength,
     ShallowBorrow,
 }
@@ -1191,14 +1190,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
 
             Rvalue::Len(ref place) | Rvalue::Discriminant(ref place) => {
                 let af = match *rvalue {
-                    Rvalue::Len(..) => ArtificialField::ArrayLength,
-                    Rvalue::Discriminant(..) => ArtificialField::Discriminant,
+                    Rvalue::Len(..) => Some(ArtificialField::ArrayLength),
+                    Rvalue::Discriminant(..) => None,
                     _ => unreachable!(),
                 };
                 self.access_place(
                     context,
                     (place, span),
-                    (Shallow(Some(af)), Read(ReadKind::Copy)),
+                    (Shallow(af), Read(ReadKind::Copy)),
                     LocalMutationIsAllowed::No,
                     flow_state,
                 );
diff --git a/src/librustc_mir/borrow_check/nll/invalidation.rs b/src/librustc_mir/borrow_check/nll/invalidation.rs
index 8af23a8813a..07bda8af626 100644
--- a/src/librustc_mir/borrow_check/nll/invalidation.rs
+++ b/src/librustc_mir/borrow_check/nll/invalidation.rs
@@ -99,7 +99,7 @@ impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> {
                 self.mutate_place(
                     ContextKind::SetDiscrim.new(location),
                     place,
-                    Shallow(Some(ArtificialField::Discriminant)),
+                    Shallow(None),
                     JustWrite,
                 );
             }
@@ -360,14 +360,14 @@ impl<'cg, 'cx, 'tcx, 'gcx> InvalidationGenerator<'cx, 'tcx, 'gcx> {
 
             Rvalue::Len(ref place) | Rvalue::Discriminant(ref place) => {
                 let af = match *rvalue {
-                    Rvalue::Len(..) => ArtificialField::ArrayLength,
-                    Rvalue::Discriminant(..) => ArtificialField::Discriminant,
+                    Rvalue::Len(..) => Some(ArtificialField::ArrayLength),
+                    Rvalue::Discriminant(..) => None,
                     _ => unreachable!(),
                 };
                 self.access_place(
                     context,
                     place,
-                    (Shallow(Some(af)), Read(ReadKind::Copy)),
+                    (Shallow(af), Read(ReadKind::Copy)),
                     LocalMutationIsAllowed::No,
                 );
             }
diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs
index eeac915cff3..e24586cca09 100644
--- a/src/librustc_mir/borrow_check/places_conflict.rs
+++ b/src/librustc_mir/borrow_check/places_conflict.rs
@@ -165,15 +165,12 @@ fn place_components_conflict<'gcx, 'tcx>(
                 let base_ty = base.ty(mir, tcx).to_ty(tcx);
 
                 match (elem, &base_ty.sty, access) {
-                    (_, _, Shallow(Some(ArtificialField::Discriminant)))
-                    | (_, _, Shallow(Some(ArtificialField::ArrayLength)))
+                    (_, _, Shallow(Some(ArtificialField::ArrayLength)))
                     | (_, _, Shallow(Some(ArtificialField::ShallowBorrow))) => {
-                        // The discriminant and array length are like
-                        // additional fields on the type; they do not
-                        // overlap any existing data there. Furthermore,
-                        // they cannot actually be a prefix of any
-                        // borrowed place (at least in MIR as it is
-                        // currently.)
+                        // The array length is like  additional fields on the
+                        // type; it does not overlap any existing data there.
+                        // Furthermore, if cannot actually be a prefix of any
+                        // borrowed place (at least in MIR as it is currently.)
                         //
                         // e.g., a (mutable) borrow of `a[5]` while we read the
                         // array length of `a`.
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index ab52d9be6b8..451034fd153 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -111,13 +111,6 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t
 
             let safety = match fn_sig.unsafety {
                 hir::Unsafety::Normal => Safety::Safe,
-                hir::Unsafety::Unsafe if tcx.is_min_const_fn(fn_def_id) => {
-                    // As specified in #55607, a `const unsafe fn` differs
-                    // from an `unsafe fn` in that its body is still considered
-                    // safe code by default.
-                    assert!(implicit_argument.is_none());
-                    Safety::Safe
-                },
                 hir::Unsafety::Unsafe => Safety::FnUnsafe,
             };
 
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index 6af29b74c1c..36078693840 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -311,13 +311,9 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
                            violations: &[UnsafetyViolation],
                            unsafe_blocks: &[(ast::NodeId, bool)]) {
         let safety = self.source_scope_local_data[self.source_info.scope].safety;
-        let within_unsafe = match (safety, self.min_const_fn) {
-            // Erring on the safe side, pun intended
-            (Safety::BuiltinUnsafe, true) |
-            // mir building encodes const fn bodies as safe, even for `const unsafe fn`
-            (Safety::FnUnsafe, true) => bug!("const unsafe fn body treated as inherently unsafe"),
+        let within_unsafe = match safety {
             // `unsafe` blocks are required in safe code
-            (Safety::Safe, _) => {
+            Safety::Safe => {
                 for violation in violations {
                     let mut violation = violation.clone();
                     match violation.kind {
@@ -342,9 +338,9 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
                 }
                 false
             }
-            // regular `unsafe` function bodies allow unsafe without additional unsafe blocks
-            (Safety::BuiltinUnsafe, false) | (Safety::FnUnsafe, false) => true,
-            (Safety::ExplicitUnsafe(node_id), _) => {
+            // `unsafe` function bodies allow unsafe without additional unsafe blocks
+            Safety::BuiltinUnsafe | Safety::FnUnsafe => true,
+            Safety::ExplicitUnsafe(node_id) => {
                 // mark unsafe block as used if there are any unsafe operations inside
                 if !violations.is_empty() {
                     self.used_unsafe.insert(node_id);
@@ -616,21 +612,6 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
     } in violations.iter() {
         // Report an error.
         match kind {
-            UnsafetyViolationKind::General if tcx.is_min_const_fn(def_id) => {
-                let mut err = tcx.sess.struct_span_err(
-                    source_info.span,
-                    &format!("{} is unsafe and unsafe operations \
-                            are not allowed in const fn", description));
-                err.span_label(source_info.span, &description.as_str()[..])
-                    .note(&details.as_str()[..]);
-                if tcx.fn_sig(def_id).unsafety() == hir::Unsafety::Unsafe {
-                    err.note(
-                        "unsafe action within a `const unsafe fn` still require an `unsafe` \
-                        block in contrast to regular `unsafe fn`."
-                    );
-                }
-                err.emit();
-            }
             UnsafetyViolationKind::GeneralAndConstFn |
             UnsafetyViolationKind::General => {
                 struct_span_err!(
diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs
index 42ead92783d..a5d2edbc5d4 100644
--- a/src/librustc_passes/lib.rs
+++ b/src/librustc_passes/lib.rs
@@ -41,7 +41,6 @@ pub mod ast_validation;
 pub mod rvalue_promotion;
 pub mod hir_stats;
 pub mod loops;
-mod mir_stats;
 
 __build_diagnostic_array! { librustc_passes, DIAGNOSTICS }
 
diff --git a/src/librustc_passes/mir_stats.rs b/src/librustc_passes/mir_stats.rs
deleted file mode 100644
index fb37f03a1cc..00000000000
--- a/src/librustc_passes/mir_stats.rs
+++ /dev/null
@@ -1,256 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// The visitors in this module collect sizes and counts of the most important
-// pieces of MIR. The resulting numbers are good approximations but not
-// completely accurate (some things might be counted twice, others missed).
-
-use rustc::mir::{AggregateKind, AssertMessage, BasicBlock, BasicBlockData};
-use rustc::mir::{Constant, Location, Local, LocalDecl};
-use rustc::mir::{Place, PlaceElem, PlaceProjection};
-use rustc::mir::{Mir, Operand, ProjectionElem};
-use rustc::mir::{Rvalue, SourceInfo, Statement, StatementKind};
-use rustc::mir::{Terminator, TerminatorKind, SourceScope, SourceScopeData};
-use rustc::mir::interpret::EvalErrorKind;
-use rustc::mir::visit as mir_visit;
-use rustc::ty::{self, ClosureSubsts, TyCtxt};
-use rustc::util::nodemap::{FxHashMap};
-
-struct NodeData {
-    count: usize,
-    size: usize,
-}
-
-struct StatCollector<'a, 'tcx: 'a> {
-    _tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    data: FxHashMap<&'static str, NodeData>,
-}
-
-impl<'a, 'tcx> StatCollector<'a, 'tcx> {
-
-    fn record_with_size(&mut self, label: &'static str, node_size: usize) {
-        let entry = self.data.entry(label).or_insert(NodeData {
-            count: 0,
-            size: 0,
-        });
-
-        entry.count += 1;
-        entry.size = node_size;
-    }
-
-    fn record<T>(&mut self, label: &'static str, node: &T) {
-        self.record_with_size(label, ::std::mem::size_of_val(node));
-    }
-}
-
-impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> {
-    fn visit_mir(&mut self, mir: &Mir<'tcx>) {
-        self.record("Mir", mir);
-
-        // since the `super_mir` method does not traverse the MIR of
-        // promoted rvalues, (but we still want to gather statistics
-        // on the structures represented there) we manually traverse
-        // the promoted rvalues here.
-        for promoted_mir in &mir.promoted {
-            self.visit_mir(promoted_mir);
-        }
-
-        self.super_mir(mir);
-    }
-
-    fn visit_basic_block_data(&mut self, block: BasicBlock, data: &BasicBlockData<'tcx>) {
-        self.record("BasicBlockData", data);
-        self.super_basic_block_data(block, data);
-    }
-
-    fn visit_source_scope_data(&mut self, scope_data: &SourceScopeData) {
-        self.record("SourceScopeData", scope_data);
-        self.super_source_scope_data(scope_data);
-    }
-
-    fn visit_statement(&mut self,
-                       block: BasicBlock,
-                       statement: &Statement<'tcx>,
-                       location: Location) {
-        self.record("Statement", statement);
-        self.record(match statement.kind {
-            StatementKind::Assign(..) => "StatementKind::Assign",
-            StatementKind::FakeRead(..) => "StatementKind::FakeRead",
-            StatementKind::Retag { .. } => "StatementKind::Retag",
-            StatementKind::EscapeToRaw { .. } => "StatementKind::EscapeToRaw",
-            StatementKind::SetDiscriminant { .. } => "StatementKind::SetDiscriminant",
-            StatementKind::StorageLive(..) => "StatementKind::StorageLive",
-            StatementKind::StorageDead(..) => "StatementKind::StorageDead",
-            StatementKind::InlineAsm { .. } => "StatementKind::InlineAsm",
-            StatementKind::AscribeUserType(..) => "StatementKind::AscribeUserType",
-            StatementKind::Nop => "StatementKind::Nop",
-        }, &statement.kind);
-        self.super_statement(block, statement, location);
-    }
-
-    fn visit_terminator(&mut self,
-                        block: BasicBlock,
-                        terminator: &Terminator<'tcx>,
-                        location: Location) {
-        self.record("Terminator", terminator);
-        self.super_terminator(block, terminator, location);
-    }
-
-    fn visit_terminator_kind(&mut self,
-                             block: BasicBlock,
-                             kind: &TerminatorKind<'tcx>,
-                             location: Location) {
-        self.record("TerminatorKind", kind);
-        self.record(match *kind {
-            TerminatorKind::Goto { .. } => "TerminatorKind::Goto",
-            TerminatorKind::SwitchInt { .. } => "TerminatorKind::SwitchInt",
-            TerminatorKind::Resume => "TerminatorKind::Resume",
-            TerminatorKind::Abort => "TerminatorKind::Abort",
-            TerminatorKind::Return => "TerminatorKind::Return",
-            TerminatorKind::Unreachable => "TerminatorKind::Unreachable",
-            TerminatorKind::Drop { .. } => "TerminatorKind::Drop",
-            TerminatorKind::DropAndReplace { .. } => "TerminatorKind::DropAndReplace",
-            TerminatorKind::Call { .. } => "TerminatorKind::Call",
-            TerminatorKind::Assert { .. } => "TerminatorKind::Assert",
-            TerminatorKind::GeneratorDrop => "TerminatorKind::GeneratorDrop",
-            TerminatorKind::Yield { .. } => "TerminatorKind::Yield",
-            TerminatorKind::FalseEdges { .. } => "TerminatorKind::FalseEdges",
-            TerminatorKind::FalseUnwind { .. } => "TerminatorKind::FalseUnwind",
-        }, kind);
-        self.super_terminator_kind(block, kind, location);
-    }
-
-    fn visit_assert_message(&mut self, msg: &AssertMessage<'tcx>, location: Location) {
-        self.record("AssertMessage", msg);
-        self.record(match *msg {
-            EvalErrorKind::BoundsCheck { .. } => "AssertMessage::BoundsCheck",
-            EvalErrorKind::Overflow(..) => "AssertMessage::Overflow",
-            EvalErrorKind::OverflowNeg => "AssertMessage::OverflowNeg",
-            EvalErrorKind::DivisionByZero => "AssertMessage::DivisionByZero",
-            EvalErrorKind::RemainderByZero => "AssertMessage::RemainderByZero",
-            EvalErrorKind::GeneratorResumedAfterReturn => {
-                "AssertMessage::GeneratorResumedAfterReturn"
-            }
-            EvalErrorKind::GeneratorResumedAfterPanic => {
-                "AssertMessage::GeneratorResumedAfterPanic"
-            }
-            _ => bug!(),
-        }, msg);
-        self.super_assert_message(msg, location);
-    }
-
-    fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
-        self.record("Rvalue", rvalue);
-        let rvalue_kind = match *rvalue {
-            Rvalue::Use(..) => "Rvalue::Use",
-            Rvalue::Repeat(..) => "Rvalue::Repeat",
-            Rvalue::Ref(..) => "Rvalue::Ref",
-            Rvalue::Len(..) => "Rvalue::Len",
-            Rvalue::Cast(..) => "Rvalue::Cast",
-            Rvalue::BinaryOp(..) => "Rvalue::BinaryOp",
-            Rvalue::CheckedBinaryOp(..) => "Rvalue::CheckedBinaryOp",
-            Rvalue::UnaryOp(..) => "Rvalue::UnaryOp",
-            Rvalue::Discriminant(..) => "Rvalue::Discriminant",
-            Rvalue::NullaryOp(..) => "Rvalue::NullaryOp",
-            Rvalue::Aggregate(ref kind, ref _operands) => {
-                // AggregateKind is not distinguished by visit API, so
-                // record it. (`super_rvalue` handles `_operands`.)
-                self.record(match **kind {
-                    AggregateKind::Array(_) => "AggregateKind::Array",
-                    AggregateKind::Tuple => "AggregateKind::Tuple",
-                    AggregateKind::Adt(..) => "AggregateKind::Adt",
-                    AggregateKind::Closure(..) => "AggregateKind::Closure",
-                    AggregateKind::Generator(..) => "AggregateKind::Generator",
-                }, kind);
-
-                "Rvalue::Aggregate"
-            }
-        };
-        self.record(rvalue_kind, rvalue);
-        self.super_rvalue(rvalue, location);
-    }
-
-    fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
-        self.record("Operand", operand);
-        self.record(match *operand {
-            Operand::Copy(..) => "Operand::Copy",
-            Operand::Move(..) => "Operand::Move",
-            Operand::Constant(..) => "Operand::Constant",
-        }, operand);
-        self.super_operand(operand, location);
-    }
-
-    fn visit_place(&mut self,
-                    place: &Place<'tcx>,
-                    context: mir_visit::PlaceContext<'tcx>,
-                    location: Location) {
-        self.record("Place", place);
-        self.record(match *place {
-            Place::Local(..) => "Place::Local",
-            Place::Static(..) => "Place::Static",
-            Place::Promoted(..) => "Place::Promoted",
-            Place::Projection(..) => "Place::Projection",
-        }, place);
-        self.super_place(place, context, location);
-    }
-
-    fn visit_projection(&mut self,
-                        place: &PlaceProjection<'tcx>,
-                        context: mir_visit::PlaceContext<'tcx>,
-                        location: Location) {
-        self.record("PlaceProjection", place);
-        self.super_projection(place, context, location);
-    }
-
-    fn visit_projection_elem(&mut self,
-                             place: &PlaceElem<'tcx>,
-                             location: Location) {
-        self.record("PlaceElem", place);
-        self.record(match *place {
-            ProjectionElem::Deref => "PlaceElem::Deref",
-            ProjectionElem::Subslice { .. } => "PlaceElem::Subslice",
-            ProjectionElem::Field(..) => "PlaceElem::Field",
-            ProjectionElem::Index(..) => "PlaceElem::Index",
-            ProjectionElem::ConstantIndex { .. } => "PlaceElem::ConstantIndex",
-            ProjectionElem::Downcast(..) => "PlaceElem::Downcast",
-        }, place);
-        self.super_projection_elem(place, location);
-    }
-
-    fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
-        self.record("Constant", constant);
-        self.super_constant(constant, location);
-    }
-
-    fn visit_source_info(&mut self, source_info: &SourceInfo) {
-        self.record("SourceInfo", source_info);
-        self.super_source_info(source_info);
-    }
-
-    fn visit_closure_substs(&mut self, substs: &ClosureSubsts<'tcx>, _: Location) {
-        self.record("ClosureSubsts", substs);
-        self.super_closure_substs(substs);
-    }
-
-    fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, _: Location) {
-        self.record("Const", constant);
-        self.super_const(constant);
-    }
-
-    fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
-        self.record("LocalDecl", local_decl);
-        self.super_local_decl(local, local_decl);
-    }
-
-    fn visit_source_scope(&mut self, scope: &SourceScope) {
-        self.record("VisiblityScope", scope);
-        self.super_source_scope(scope);
-    }
-}
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index e4ce04916ce..75ae8688834 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -280,7 +280,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                         Def::Local(id) | Def::Upvar(id, ..) => {
                             Some(self.tcx.hir().span(id))
                         }
-                        _ => self.tcx.hir().span_if_local(def.def_id())
+                        _ => def.opt_def_id().and_then(|did| self.tcx.hir().span_if_local(did)),
                     };
                     if let Some(span) = def_span {
                         let label = match (unit_variant, inner_callee_path) {
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 8901f4b6b29..957c8d9f19f 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -95,7 +95,7 @@ mod op;
 
 use astconv::AstConv;
 use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
-use rustc::hir::{self, GenericArg, Node, ItemKind, PatKind};
+use rustc::hir::{self, GenericArg, ItemKind, Node, PatKind};
 use rustc::hir::def::Def;
 use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
@@ -113,7 +113,8 @@ use rustc::mir::interpret::{ConstValue, GlobalId};
 use rustc::ty::subst::{CanonicalUserSubsts, UnpackedKind, Subst, Substs,
                        UserSelfTy, UserSubsts};
 use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine};
-use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind, Visibility, ToPredicate, RegionKind};
+use rustc::ty::{self, AdtKind, Ty, TyCtxt, GenericParamDefKind, Visibility, ToPredicate,
+                RegionKind};
 use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::query::Providers;
@@ -3217,8 +3218,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                             return_expr_ty);
     }
 
-    // A generic function for checking the then and else in an if
-    // or if-else.
+    // A generic function for checking the 'then' and 'else' clauses in an 'if'
+    // or 'if-else' expression.
     fn check_then_else(&self,
                        cond_expr: &'gcx hir::Expr,
                        then_expr: &'gcx hir::Expr,
@@ -3544,7 +3545,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 // We don't look at stability attributes on
                 // struct-like enums (yet...), but it's definitely not
                 // a bug to have constructed one.
-                if adt_kind != ty::AdtKind::Enum {
+                if adt_kind != AdtKind::Enum {
                     tcx.check_stability(v_field.did, Some(expr_id), field.span);
                 }
 
@@ -5156,26 +5157,48 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         }).unwrap_or(false);
 
         let mut new_def = def;
-        let (def_id, ty) = if let Def::SelfCtor(impl_def_id) = def {
-            let ty = self.impl_self_ty(span, impl_def_id).ty;
-
-            match ty.ty_adt_def() {
-                Some(adt_def) if adt_def.is_struct() => {
-                    let variant = adt_def.non_enum_variant();
-                    new_def = Def::StructCtor(variant.did, variant.ctor_kind);
-                    (variant.did, self.tcx.type_of(variant.did))
-                }
-                _ => {
-                    (impl_def_id, self.tcx.types.err)
+        let (def_id, ty) = match def {
+            Def::SelfCtor(impl_def_id) => {
+                let ty = self.impl_self_ty(span, impl_def_id).ty;
+                let adt_def = ty.ty_adt_def();
+
+                match adt_def {
+                    Some(adt_def) if adt_def.has_ctor() => {
+                        let variant = adt_def.non_enum_variant();
+                        new_def = Def::StructCtor(variant.did, variant.ctor_kind);
+                        (variant.did, self.tcx.type_of(variant.did))
+                    }
+                    _ => {
+                        let mut err = self.tcx.sess.struct_span_err(span,
+                            "the `Self` constructor can only be used with tuple or unit structs");
+                        if let Some(adt_def) = adt_def {
+                            match adt_def.adt_kind() {
+                                AdtKind::Enum => {
+                                    err.note("did you mean to use one of the enum's variants?");
+                                },
+                                AdtKind::Struct |
+                                AdtKind::Union => {
+                                    err.span_label(
+                                        span,
+                                        format!("did you mean `Self {{ /* fields */ }}`?"),
+                                    );
+                                }
+                            }
+                        }
+                        err.emit();
+
+                        (impl_def_id, self.tcx.types.err)
+                    }
                 }
             }
-        } else {
-            let def_id = def.def_id();
+            _ => {
+                let def_id = def.def_id();
 
-            // The things we are substituting into the type should not contain
-            // escaping late-bound regions, and nor should the base type scheme.
-            let ty = self.tcx.type_of(def_id);
-            (def_id, ty)
+                // The things we are substituting into the type should not contain
+                // escaping late-bound regions, and nor should the base type scheme.
+                let ty = self.tcx.type_of(def_id);
+                (def_id, ty)
+            }
         };
 
         let substs = AstConv::create_substs_for_generic_args(
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index d1336b1e8eb..01d2cbec192 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -305,7 +305,7 @@ nav.sub {
 	overflow-x: auto;
 }
 
-body:not(.source) .example-wrap > pre {
+.rustdoc:not(.source) .example-wrap > pre {
 	margin: 0;
 }
 
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index 50acde64cf0..84ce9f6d257 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -395,6 +395,7 @@ pub fn make_test(s: &str,
     // Now push any outer attributes from the example, assuming they
     // are intended to be crate attributes.
     prog.push_str(&crate_attrs);
+    prog.push_str(&crates);
 
     // Uses libsyntax to parse the doctest and find if there's a main fn and the extern
     // crate already is included.
@@ -488,37 +489,78 @@ pub fn make_test(s: &str,
         prog.push_str("\n}");
     }
 
+    debug!("final doctest:\n{}", prog);
+
     (prog, line_offset)
 }
 
 // FIXME(aburka): use a real parser to deal with multiline attributes
 fn partition_source(s: &str) -> (String, String, String) {
-    let mut after_header = false;
+    #[derive(Copy, Clone, PartialEq)]
+    enum PartitionState {
+        Attrs,
+        Crates,
+        Other,
+    }
+    let mut state = PartitionState::Attrs;
     let mut before = String::new();
     let mut crates = String::new();
     let mut after = String::new();
 
     for line in s.lines() {
         let trimline = line.trim();
-        let header = trimline.chars().all(|c| c.is_whitespace()) ||
-            trimline.starts_with("#![") ||
-            trimline.starts_with("#[macro_use] extern crate") ||
-            trimline.starts_with("extern crate");
-        if !header || after_header {
-            after_header = true;
-            after.push_str(line);
-            after.push_str("\n");
-        } else {
-            if trimline.starts_with("#[macro_use] extern crate")
-                || trimline.starts_with("extern crate") {
+
+        // FIXME(misdreavus): if a doc comment is placed on an extern crate statement, it will be
+        // shunted into "everything else"
+        match state {
+            PartitionState::Attrs => {
+                state = if trimline.starts_with("#![") ||
+                    trimline.chars().all(|c| c.is_whitespace()) ||
+                    (trimline.starts_with("//") && !trimline.starts_with("///"))
+                {
+                    PartitionState::Attrs
+                } else if trimline.starts_with("extern crate") ||
+                    trimline.starts_with("#[macro_use] extern crate")
+                {
+                    PartitionState::Crates
+                } else {
+                    PartitionState::Other
+                };
+            }
+            PartitionState::Crates => {
+                state = if trimline.starts_with("extern crate") ||
+                    trimline.starts_with("#[macro_use] extern crate") ||
+                    trimline.chars().all(|c| c.is_whitespace()) ||
+                    (trimline.starts_with("//") && !trimline.starts_with("///"))
+                {
+                    PartitionState::Crates
+                } else {
+                    PartitionState::Other
+                };
+            }
+            PartitionState::Other => {}
+        }
+
+        match state {
+            PartitionState::Attrs => {
+                before.push_str(line);
+                before.push_str("\n");
+            }
+            PartitionState::Crates => {
                 crates.push_str(line);
                 crates.push_str("\n");
             }
-            before.push_str(line);
-            before.push_str("\n");
+            PartitionState::Other => {
+                after.push_str(line);
+                after.push_str("\n");
+            }
         }
     }
 
+    debug!("before:\n{}", before);
+    debug!("crates:\n{}", crates);
+    debug!("after:\n{}", after);
+
     (before, after, crates)
 }
 
@@ -1035,8 +1077,8 @@ fn main() {
 assert_eq!(2+2, 4);";
         let expected =
 "#![allow(unused)]
-fn main() {
 //Ceci n'est pas une `fn main`
+fn main() {
 assert_eq!(2+2, 4);
 }".to_string();
         let output = make_test(input, None, false, &opts);
@@ -1083,8 +1125,8 @@ assert_eq!(2+2, 4);";
 
         let expected =
 "#![allow(unused)]
-fn main() {
 // fn main
+fn main() {
 assert_eq!(2+2, 4);
 }".to_string();
 
diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml
index 41e778b6a4c..9cee00b9c76 100644
--- a/src/libstd/Cargo.toml
+++ b/src/libstd/Cargo.toml
@@ -21,6 +21,7 @@ libc = { version = "0.2.44", default-features = false, features = ['rustc-dep-of
 compiler_builtins = { version = "0.1.1" }
 profiler_builtins = { path = "../libprofiler_builtins", optional = true }
 unwind = { path = "../libunwind" }
+rustc-demangle = { version = "0.1.10", features = ['rustc-dep-of-std'] }
 
 [dev-dependencies]
 rand = "0.6.1"
diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs
index 7d17aaf2f26..d0dd4d4adcb 100644
--- a/src/libstd/f32.rs
+++ b/src/libstd/f32.rs
@@ -550,7 +550,8 @@ impl f32 {
     #[inline]
     #[rustc_deprecated(since = "1.10.0",
                        reason = "you probably meant `(self - other).abs()`: \
-                                 this operation is `(self - other).max(0.0)` (also \
+                                 this operation is `(self - other).max(0.0)` \
+                                 except that `abs_sub` also propagates NaNs (also \
                                  known as `fdimf` in C). If you truly need the positive \
                                  difference, consider using that expression or the C function \
                                  `fdimf`, depending on how you wish to handle NaN (please consider \
diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs
index c800763167f..9e627ec2042 100644
--- a/src/libstd/f64.rs
+++ b/src/libstd/f64.rs
@@ -491,7 +491,8 @@ impl f64 {
     #[inline]
     #[rustc_deprecated(since = "1.10.0",
                        reason = "you probably meant `(self - other).abs()`: \
-                                 this operation is `(self - other).max(0.0)` (also \
+                                 this operation is `(self - other).max(0.0)` \
+                                 except that `abs_sub` also propagates NaNs (also \
                                  known as `fdim` in C). If you truly need the positive \
                                  difference, consider using that expression or the C function \
                                  `fdim`, depending on how you wish to handle NaN (please consider \
diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs
index edcfdd9e534..35ae4939249 100644
--- a/src/libstd/fs.rs
+++ b/src/libstd/fs.rs
@@ -1729,7 +1729,7 @@ pub fn read_link<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
 /// limited to just these cases:
 ///
 /// * `path` does not exist.
-/// * A component in path is not a directory.
+/// * A non-final component in path is not a directory.
 ///
 /// # Examples
 ///
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 0febbe5694b..ead38f21126 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -339,6 +339,7 @@ pub use core::{unreachable, unimplemented, write, writeln, try};
 extern crate alloc as alloc_crate;
 #[doc(masked)]
 extern crate libc;
+extern crate rustc_demangle;
 
 // We always need an unwinder currently for backtraces
 #[doc(masked)]
diff --git a/src/libstd/os/raw/mod.rs b/src/libstd/os/raw/mod.rs
index 95faf3a5dd6..05f30f2881a 100644
--- a/src/libstd/os/raw/mod.rs
+++ b/src/libstd/os/raw/mod.rs
@@ -27,6 +27,10 @@
           all(target_os = "android", any(target_arch = "aarch64",
                                          target_arch = "arm")),
           all(target_os = "l4re", target_arch = "x86_64"),
+          all(target_os = "freebsd", any(target_arch = "aarch64",
+                                         target_arch = "arm",
+                                         target_arch = "powerpc",
+                                         target_arch = "powerpc64")),
           all(target_os = "netbsd", any(target_arch = "aarch64",
                                         target_arch = "arm",
                                         target_arch = "powerpc")),
@@ -42,6 +46,10 @@
               all(target_os = "android", any(target_arch = "aarch64",
                                              target_arch = "arm")),
               all(target_os = "l4re", target_arch = "x86_64"),
+              all(target_os = "freebsd", any(target_arch = "aarch64",
+                                             target_arch = "arm",
+                                             target_arch = "powerpc",
+                                             target_arch = "powerpc64")),
               all(target_os = "netbsd", any(target_arch = "aarch64",
                                             target_arch = "arm",
                                             target_arch = "powerpc")),
diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs
index 77371782977..e44113f76f4 100644
--- a/src/libstd/sys_common/backtrace.rs
+++ b/src/libstd/sys_common/backtrace.rs
@@ -14,11 +14,12 @@
 use env;
 use io::prelude::*;
 use io;
+use path::{self, Path};
+use ptr;
+use rustc_demangle::demangle;
 use str;
 use sync::atomic::{self, Ordering};
-use path::{self, Path};
 use sys::mutex::Mutex;
-use ptr;
 
 pub use sys::backtrace::{
     unwind_backtrace,
@@ -191,7 +192,14 @@ fn output(w: &mut dyn Write, idx: usize, frame: Frame,
         PrintFormat::Short => write!(w, "  {:2}: ", idx)?,
     }
     match s {
-        Some(string) => demangle(w, string, format)?,
+        Some(string) => {
+            let symbol = demangle(string);
+            match format {
+                PrintFormat::Full => write!(w, "{}", symbol)?,
+                // strip the trailing hash if short mode
+                PrintFormat::Short => write!(w, "{:#}", symbol)?,
+            }
+        }
         None => w.write_all(b"<unknown>")?,
     }
     w.write_all(b"\n")
@@ -235,228 +243,3 @@ fn output_fileline(w: &mut dyn Write,
     w.write_all(b"\n")
 }
 
-
-// All rust symbols are in theory lists of "::"-separated identifiers. Some
-// assemblers, however, can't handle these characters in symbol names. To get
-// around this, we use C++-style mangling. The mangling method is:
-//
-// 1. Prefix the symbol with "_ZN"
-// 2. For each element of the path, emit the length plus the element
-// 3. End the path with "E"
-//
-// For example, "_ZN4testE" => "test" and "_ZN3foo3barE" => "foo::bar".
-//
-// We're the ones printing our backtraces, so we can't rely on anything else to
-// demangle our symbols. It's *much* nicer to look at demangled symbols, so
-// this function is implemented to give us nice pretty output.
-//
-// Note that this demangler isn't quite as fancy as it could be. We have lots
-// of other information in our symbols like hashes, version, type information,
-// etc. Additionally, this doesn't handle glue symbols at all.
-pub fn demangle(writer: &mut dyn Write, mut s: &str, format: PrintFormat) -> io::Result<()> {
-    // During ThinLTO LLVM may import and rename internal symbols, so strip out
-    // those endings first as they're one of the last manglings applied to
-    // symbol names.
-    let llvm = ".llvm.";
-    if let Some(i) = s.find(llvm) {
-        let candidate = &s[i + llvm.len()..];
-        let all_hex = candidate.chars().all(|c| {
-            match c {
-                'A' ..= 'F' | '0' ..= '9' => true,
-                _ => false,
-            }
-        });
-
-        if all_hex {
-            s = &s[..i];
-        }
-    }
-
-    // Validate the symbol. If it doesn't look like anything we're
-    // expecting, we just print it literally. Note that we must handle non-rust
-    // symbols because we could have any function in the backtrace.
-    let mut valid = true;
-    let mut inner = s;
-    if s.len() > 4 && s.starts_with("_ZN") && s.ends_with("E") {
-        inner = &s[3 .. s.len() - 1];
-    // On Windows, dbghelp strips leading underscores, so we accept "ZN...E" form too.
-    } else if s.len() > 3 && s.starts_with("ZN") && s.ends_with("E") {
-        inner = &s[2 .. s.len() - 1];
-    } else {
-        valid = false;
-    }
-
-    if valid {
-        let mut chars = inner.chars();
-        while valid {
-            let mut i = 0;
-            for c in chars.by_ref() {
-                if c.is_numeric() {
-                    i = i * 10 + c as usize - '0' as usize;
-                } else {
-                    break
-                }
-            }
-            if i == 0 {
-                valid = chars.next().is_none();
-                break
-            } else if chars.by_ref().take(i - 1).count() != i - 1 {
-                valid = false;
-            }
-        }
-    }
-
-    // Alright, let's do this.
-    if !valid {
-        writer.write_all(s.as_bytes())?;
-    } else {
-        // remove the `::hfc2edb670e5eda97` part at the end of the symbol.
-        if format == PrintFormat::Short {
-            // The symbol in still mangled.
-            let mut split = inner.rsplitn(2, "17h");
-            match (split.next(), split.next()) {
-                (Some(addr), rest) => {
-                    if addr.len() == 16 &&
-                       addr.chars().all(|c| c.is_digit(16))
-                    {
-                        inner = rest.unwrap_or("");
-                    }
-                }
-                _ => (),
-            }
-        }
-
-        let mut first = true;
-        while !inner.is_empty() {
-            if !first {
-                writer.write_all(b"::")?;
-            } else {
-                first = false;
-            }
-            let mut rest = inner;
-            while rest.chars().next().unwrap().is_numeric() {
-                rest = &rest[1..];
-            }
-            let i: usize = inner[.. (inner.len() - rest.len())].parse().unwrap();
-            inner = &rest[i..];
-            rest = &rest[..i];
-            if rest.starts_with("_$") {
-                rest = &rest[1..];
-            }
-            while !rest.is_empty() {
-                if rest.starts_with(".") {
-                    if let Some('.') = rest[1..].chars().next() {
-                        writer.write_all(b"::")?;
-                        rest = &rest[2..];
-                    } else {
-                        writer.write_all(b".")?;
-                        rest = &rest[1..];
-                    }
-                } else if rest.starts_with("$") {
-                    macro_rules! demangle {
-                        ($($pat:expr => $demangled:expr),*) => ({
-                            $(if rest.starts_with($pat) {
-                                writer.write_all($demangled)?;
-                                rest = &rest[$pat.len()..];
-                              } else)*
-                            {
-                                writer.write_all(rest.as_bytes())?;
-                                break;
-                            }
-
-                        })
-                    }
-
-                    // see src/librustc/back/link.rs for these mappings
-                    demangle! (
-                        "$SP$" => b"@",
-                        "$BP$" => b"*",
-                        "$RF$" => b"&",
-                        "$LT$" => b"<",
-                        "$GT$" => b">",
-                        "$LP$" => b"(",
-                        "$RP$" => b")",
-                        "$C$" => b",",
-
-                        // in theory we can demangle any Unicode code point, but
-                        // for simplicity we just catch the common ones.
-                        "$u7e$" => b"~",
-                        "$u20$" => b" ",
-                        "$u27$" => b"'",
-                        "$u5b$" => b"[",
-                        "$u5d$" => b"]",
-                        "$u7b$" => b"{",
-                        "$u7d$" => b"}",
-                        "$u3b$" => b";",
-                        "$u2b$" => b"+",
-                        "$u22$" => b"\""
-                    )
-                } else {
-                    let idx = match rest.char_indices().find(|&(_, c)| c == '$' || c == '.') {
-                        None => rest.len(),
-                        Some((i, _)) => i,
-                    };
-                    writer.write_all(rest[..idx].as_bytes())?;
-                    rest = &rest[idx..];
-                }
-            }
-        }
-    }
-
-    Ok(())
-}
-
-#[cfg(test)]
-mod tests {
-    use sys_common;
-    macro_rules! t { ($a:expr, $b:expr) => ({
-        let mut m = Vec::new();
-        sys_common::backtrace::demangle(&mut m,
-                                        $a,
-                                        super::PrintFormat::Full).unwrap();
-        assert_eq!(String::from_utf8(m).unwrap(), $b);
-    }) }
-
-    #[test]
-    fn demangle() {
-        t!("test", "test");
-        t!("_ZN4testE", "test");
-        t!("_ZN4test", "_ZN4test");
-        t!("_ZN4test1a2bcE", "test::a::bc");
-    }
-
-    #[test]
-    fn demangle_dollars() {
-        t!("_ZN4$RP$E", ")");
-        t!("_ZN8$RF$testE", "&test");
-        t!("_ZN8$BP$test4foobE", "*test::foob");
-        t!("_ZN9$u20$test4foobE", " test::foob");
-        t!("_ZN35Bar$LT$$u5b$u32$u3b$$u20$4$u5d$$GT$E", "Bar<[u32; 4]>");
-    }
-
-    #[test]
-    fn demangle_many_dollars() {
-        t!("_ZN13test$u20$test4foobE", "test test::foob");
-        t!("_ZN12test$BP$test4foobE", "test*test::foob");
-    }
-
-    #[test]
-    fn demangle_windows() {
-        t!("ZN4testE", "test");
-        t!("ZN13test$u20$test4foobE", "test test::foob");
-        t!("ZN12test$RF$test4foobE", "test&test::foob");
-    }
-
-    #[test]
-    fn demangle_elements_beginning_with_underscore() {
-        t!("_ZN13_$LT$test$GT$E", "<test>");
-        t!("_ZN28_$u7b$$u7b$closure$u7d$$u7d$E", "{{closure}}");
-        t!("_ZN15__STATIC_FMTSTRE", "__STATIC_FMTSTR");
-    }
-
-    #[test]
-    fn demangle_trait_impls() {
-        t!("_ZN71_$LT$Test$u20$$u2b$$u20$$u27$static$u20$as$u20$foo..Bar$LT$Test$GT$$GT$3barE",
-           "<Test + 'static as foo::Bar<Test>>::bar");
-    }
-}
diff --git a/src/llvm b/src/llvm
-Subproject a784eca10d2c1f09e65d67e16eca266485e1eac
+Subproject 95185c8c801c765ac1072392d081d265af9fb31
diff --git a/src/rustllvm/llvm-rebuild-trigger b/src/rustllvm/llvm-rebuild-trigger
index 9cf17c45e87..a268838de45 100644
--- a/src/rustllvm/llvm-rebuild-trigger
+++ b/src/rustllvm/llvm-rebuild-trigger
@@ -1,4 +1,4 @@
 # If this file is modified, then llvm will be (optionally) cleaned and then rebuilt.
 # The actual contents of this file do not matter, but to trigger a change on the
 # build bots then the contents should be changed so git updates the mtime.
-2018-11-28
+2018-12-13
diff --git a/src/test/rustdoc/comment-in-doctest.rs b/src/test/rustdoc/comment-in-doctest.rs
new file mode 100644
index 00000000000..3468bb7bda4
--- /dev/null
+++ b/src/test/rustdoc/comment-in-doctest.rs
@@ -0,0 +1,30 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags:--test
+
+// comments, both doc comments and regular ones, used to trick rustdoc's doctest parser into
+// thinking that everything after it was part of the regular program. combined with the libsyntax
+// parser loop failing to detect the manual main function, it would wrap everything in `fn main`,
+// which would cause the doctest to fail as the "extern crate" declaration was no longer valid.
+// oddly enough, it would pass in 2018 if a crate was in the extern prelude. see
+// https://github.com/rust-lang/rust/issues/56727
+
+//! ```
+//! // crate: proc-macro-test
+//! //! this is a test
+//!
+//! // used to pull in proc-macro specific items
+//! extern crate proc_macro;
+//!
+//! use proc_macro::TokenStream;
+//!
+//! # fn main() {}
+//! ```
diff --git a/src/test/ui/borrowck/borrowck-anon-fields-variant.nll.stderr b/src/test/ui/borrowck/borrowck-anon-fields-variant.nll.stderr
index 17722bf226d..6f72de0edee 100644
--- a/src/test/ui/borrowck/borrowck-anon-fields-variant.nll.stderr
+++ b/src/test/ui/borrowck/borrowck-anon-fields-variant.nll.stderr
@@ -1,3 +1,31 @@
+warning[E0503]: cannot use `y` because it was mutably borrowed
+  --> $DIR/borrowck-anon-fields-variant.rs:27:7
+   |
+LL |       Foo::Y(ref mut a, _) => a,
+   |              --------- borrow of `y.0` occurs here
+...
+LL |       Foo::Y(_, ref mut b) => b,
+   |       ^^^^^^^^^^^^^^^^^^^^ use of borrowed `y.0`
+...
+LL |     *a += 1;
+   |     ------- borrow later used here
+   |
+   = warning: This error has been downgraded to a warning for backwards compatibility with previous releases.
+           It represents potential unsoundness in your code.
+           This warning will become a hard error in the future.
+
+error[E0503]: cannot use `y` because it was mutably borrowed
+  --> $DIR/borrowck-anon-fields-variant.rs:44:7
+   |
+LL |       Foo::Y(ref mut a, _) => a,
+   |              --------- borrow of `y.0` occurs here
+...
+LL |       Foo::Y(ref mut b, _) => b, //~ ERROR cannot borrow
+   |       ^^^^^^^^^^^^^^^^^^^^ use of borrowed `y.0`
+...
+LL |     *a += 1;
+   |     ------- borrow later used here
+
 error[E0499]: cannot borrow `y.0` as mutable more than once at a time
   --> $DIR/borrowck-anon-fields-variant.rs:44:14
    |
@@ -10,6 +38,7 @@ LL |       Foo::Y(ref mut b, _) => b, //~ ERROR cannot borrow
 LL |     *a += 1;
    |     ------- first borrow later used here
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0499`.
+Some errors occurred: E0499, E0503.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs
index f11b43dcd86..92e99c6228a 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs
+++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs
@@ -28,13 +28,13 @@ const fn call_unsafe_generic_cell_const_fn() -> *const Vec<std::cell::Cell<u32>>
     unsafe { ret_null_mut_ptr_no_unsafe::<Vec<std::cell::Cell<u32>>>() }
     //~^ ERROR calls to `const unsafe fn` in const fns
 }
-const unsafe fn deref_forbidden(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn
+const unsafe fn deref_forbidden(x: *mut usize) -> usize { *x }
 //~^ dereferencing raw pointers in constant functions
 
 fn main() {}
 
 const unsafe fn no_union() {
     union Foo { x: (), y: () }
-    Foo { x: () }.y //~ ERROR not allowed in const fn
+    Foo { x: () }.y
     //~^ unions in const fn
 }
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr
index 922a7883b9f..fafc89d1493 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr
@@ -1,7 +1,7 @@
 error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911)
   --> $DIR/min_const_fn_unsafe.rs:31:59
    |
-LL | const unsafe fn deref_forbidden(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn
+LL | const unsafe fn deref_forbidden(x: *mut usize) -> usize { *x }
    |                                                           ^^
    |
    = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
@@ -9,7 +9,7 @@ LL | const unsafe fn deref_forbidden(x: *mut usize) -> usize { *x } //~ ERROR no
 error[E0658]: unions in const fn are unstable (see issue #51909)
   --> $DIR/min_const_fn_unsafe.rs:38:5
    |
-LL |     Foo { x: () }.y //~ ERROR not allowed in const fn
+LL |     Foo { x: () }.y
    |     ^^^^^^^^^^^^^^^
    |
    = help: add #![feature(const_fn_union)] to the crate attributes to enable
@@ -38,24 +38,6 @@ LL |     unsafe { ret_null_mut_ptr_no_unsafe::<Vec<std::cell::Cell<u32>>>() }
    |
    = help: add #![feature(min_const_unsafe_fn)] to the crate attributes to enable
 
-error: dereference of raw pointer is unsafe and unsafe operations are not allowed in const fn
-  --> $DIR/min_const_fn_unsafe.rs:31:59
-   |
-LL | const unsafe fn deref_forbidden(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn
-   |                                                           ^^ dereference of raw pointer
-   |
-   = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
-   = note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
-
-error: access to union field is unsafe and unsafe operations are not allowed in const fn
-  --> $DIR/min_const_fn_unsafe.rs:38:5
-   |
-LL |     Foo { x: () }.y //~ ERROR not allowed in const fn
-   |     ^^^^^^^^^^^^^^^ access to union field
-   |
-   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
-   = note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
-
-error: aborting due to 7 previous errors
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.rs b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.rs
index 8a6884bc6b9..67a48206126 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.rs
+++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.rs
@@ -34,29 +34,28 @@ const unsafe fn foo9_3() -> *const String {
 const unsafe fn foo10_3() -> *const Vec<std::cell::Cell<u32>> {
     unsafe { foo6::<Vec<std::cell::Cell<u32>>>() }
 }
-// not ok
 const unsafe fn foo8_2() -> i32 {
-    foo4() //~ ERROR not allowed in const fn
+    foo4()
 }
 const unsafe fn foo9_2() -> *const String {
-    foo5::<String>() //~ ERROR not allowed in const fn
+    foo5::<String>()
 }
 const unsafe fn foo10_2() -> *const Vec<std::cell::Cell<u32>> {
-    foo6::<Vec<std::cell::Cell<u32>>>() //~ ERROR not allowed in const fn
+    foo6::<Vec<std::cell::Cell<u32>>>()
 }
-const unsafe fn foo30_3(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn
+const unsafe fn foo30_3(x: *mut usize) -> usize { *x }
 //~^ dereferencing raw pointers in constant functions
 
-const unsafe fn foo30_4(x: *mut usize) -> &'static usize { &*x } //~ ERROR not allowed in const fn
+const unsafe fn foo30_4(x: *mut usize) -> &'static usize { &*x }
 //~^ dereferencing raw pointers in constant functions
 
-const fn foo30_5(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ ERROR not allowed
+const fn foo30_5(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ is unsafe
 //~^ dereferencing raw pointers in constant functions
 
 fn main() {}
 
 const unsafe fn no_union() {
     union Foo { x: (), y: () }
-    Foo { x: () }.y //~ ERROR not allowed in const fn
+    Foo { x: () }.y
     //~^ unions in const fn
 }
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.stderr
index 20c75afbe63..63bf9a53e50 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.stderr
@@ -1,97 +1,44 @@
 error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911)
-  --> $DIR/min_const_fn_unsafe_feature_gate.rs:47:51
+  --> $DIR/min_const_fn_unsafe_feature_gate.rs:46:51
    |
-LL | const unsafe fn foo30_3(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn
+LL | const unsafe fn foo30_3(x: *mut usize) -> usize { *x }
    |                                                   ^^
    |
    = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
 
 error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911)
-  --> $DIR/min_const_fn_unsafe_feature_gate.rs:50:60
+  --> $DIR/min_const_fn_unsafe_feature_gate.rs:49:60
    |
-LL | const unsafe fn foo30_4(x: *mut usize) -> &'static usize { &*x } //~ ERROR not allowed in const fn
+LL | const unsafe fn foo30_4(x: *mut usize) -> &'static usize { &*x }
    |                                                            ^^^
    |
    = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
 
 error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911)
-  --> $DIR/min_const_fn_unsafe_feature_gate.rs:53:62
+  --> $DIR/min_const_fn_unsafe_feature_gate.rs:52:62
    |
-LL | const fn foo30_5(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ ERROR not allowed
+LL | const fn foo30_5(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ is unsafe
    |                                                              ^^^
    |
    = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
 
 error[E0658]: unions in const fn are unstable (see issue #51909)
-  --> $DIR/min_const_fn_unsafe_feature_gate.rs:60:5
+  --> $DIR/min_const_fn_unsafe_feature_gate.rs:59:5
    |
-LL |     Foo { x: () }.y //~ ERROR not allowed in const fn
+LL |     Foo { x: () }.y
    |     ^^^^^^^^^^^^^^^
    |
    = help: add #![feature(const_fn_union)] to the crate attributes to enable
 
-error: call to unsafe function is unsafe and unsafe operations are not allowed in const fn
-  --> $DIR/min_const_fn_unsafe_feature_gate.rs:39:5
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+  --> $DIR/min_const_fn_unsafe_feature_gate.rs:52:62
    |
-LL |     foo4() //~ ERROR not allowed in const fn
-   |     ^^^^^^ call to unsafe function
-   |
-   = note: consult the function's documentation for information on how to avoid undefined behavior
-   = note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
-
-error: call to unsafe function is unsafe and unsafe operations are not allowed in const fn
-  --> $DIR/min_const_fn_unsafe_feature_gate.rs:42:5
-   |
-LL |     foo5::<String>() //~ ERROR not allowed in const fn
-   |     ^^^^^^^^^^^^^^^^ call to unsafe function
-   |
-   = note: consult the function's documentation for information on how to avoid undefined behavior
-   = note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
-
-error: call to unsafe function is unsafe and unsafe operations are not allowed in const fn
-  --> $DIR/min_const_fn_unsafe_feature_gate.rs:45:5
-   |
-LL |     foo6::<Vec<std::cell::Cell<u32>>>() //~ ERROR not allowed in const fn
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
-   |
-   = note: consult the function's documentation for information on how to avoid undefined behavior
-   = note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
-
-error: dereference of raw pointer is unsafe and unsafe operations are not allowed in const fn
-  --> $DIR/min_const_fn_unsafe_feature_gate.rs:47:51
-   |
-LL | const unsafe fn foo30_3(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn
-   |                                                   ^^ dereference of raw pointer
-   |
-   = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
-   = note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
-
-error: dereference of raw pointer is unsafe and unsafe operations are not allowed in const fn
-  --> $DIR/min_const_fn_unsafe_feature_gate.rs:50:60
-   |
-LL | const unsafe fn foo30_4(x: *mut usize) -> &'static usize { &*x } //~ ERROR not allowed in const fn
-   |                                                            ^^^ dereference of raw pointer
-   |
-   = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
-   = note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
-
-error: dereference of raw pointer is unsafe and unsafe operations are not allowed in const fn
-  --> $DIR/min_const_fn_unsafe_feature_gate.rs:53:62
-   |
-LL | const fn foo30_5(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ ERROR not allowed
+LL | const fn foo30_5(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ is unsafe
    |                                                              ^^^ dereference of raw pointer
    |
    = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
 
-error: access to union field is unsafe and unsafe operations are not allowed in const fn
-  --> $DIR/min_const_fn_unsafe_feature_gate.rs:60:5
-   |
-LL |     Foo { x: () }.y //~ ERROR not allowed in const fn
-   |     ^^^^^^^^^^^^^^^ access to union field
-   |
-   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
-   = note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
-
-error: aborting due to 11 previous errors
+error: aborting due to 5 previous errors
 
-For more information about this error, try `rustc --explain E0658`.
+Some errors occurred: E0133, E0658.
+For more information about an error, try `rustc --explain E0133`.
diff --git a/src/test/ui/issues/issue-56199.rs b/src/test/ui/issues/issue-56199.rs
new file mode 100644
index 00000000000..83d4e31b5d1
--- /dev/null
+++ b/src/test/ui/issues/issue-56199.rs
@@ -0,0 +1,23 @@
+
+enum Foo {}
+struct Bar {}
+
+impl Foo {
+    fn foo() {
+        let _ = Self;
+        //~^ ERROR the `Self` constructor can only be used with tuple or unit structs
+        let _ = Self();
+        //~^ ERROR the `Self` constructor can only be used with tuple or unit structs
+    }
+}
+
+impl Bar {
+    fn bar() {
+        let _ = Self;
+        //~^ ERROR the `Self` constructor can only be used with tuple or unit structs
+        let _ = Self();
+        //~^ ERROR the `Self` constructor can only be used with tuple or unit structs
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-56199.stderr b/src/test/ui/issues/issue-56199.stderr
new file mode 100644
index 00000000000..6e3c7fd17b4
--- /dev/null
+++ b/src/test/ui/issues/issue-56199.stderr
@@ -0,0 +1,30 @@
+error: the `Self` constructor can only be used with tuple or unit structs
+  --> $DIR/issue-56199.rs:7:17
+   |
+LL |         let _ = Self;
+   |                 ^^^^
+   |
+   = note: did you mean to use one of the enum's variants?
+
+error: the `Self` constructor can only be used with tuple or unit structs
+  --> $DIR/issue-56199.rs:9:17
+   |
+LL |         let _ = Self();
+   |                 ^^^^
+   |
+   = note: did you mean to use one of the enum's variants?
+
+error: the `Self` constructor can only be used with tuple or unit structs
+  --> $DIR/issue-56199.rs:16:17
+   |
+LL |         let _ = Self;
+   |                 ^^^^ did you mean `Self { /* fields */ }`?
+
+error: the `Self` constructor can only be used with tuple or unit structs
+  --> $DIR/issue-56199.rs:18:17
+   |
+LL |         let _ = Self();
+   |                 ^^^^ did you mean `Self { /* fields */ }`?
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/issues/issue-56835.rs b/src/test/ui/issues/issue-56835.rs
new file mode 100644
index 00000000000..c16550e3701
--- /dev/null
+++ b/src/test/ui/issues/issue-56835.rs
@@ -0,0 +1,10 @@
+
+pub struct Foo {}
+
+impl Foo {
+    fn bar(Self(foo): Self) {}
+    //~^ ERROR the `Self` constructor can only be used with tuple or unit structs
+    //~^^ ERROR expected tuple struct/variant, found self constructor `Self` [E0164]
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-56835.stderr b/src/test/ui/issues/issue-56835.stderr
new file mode 100644
index 00000000000..b7c3b142ec4
--- /dev/null
+++ b/src/test/ui/issues/issue-56835.stderr
@@ -0,0 +1,15 @@
+error: the `Self` constructor can only be used with tuple or unit structs
+  --> $DIR/issue-56835.rs:5:12
+   |
+LL |     fn bar(Self(foo): Self) {}
+   |            ^^^^^^^^^ did you mean `Self { /* fields */ }`?
+
+error[E0164]: expected tuple struct/variant, found self constructor `Self`
+  --> $DIR/issue-56835.rs:5:12
+   |
+LL |     fn bar(Self(foo): Self) {}
+   |            ^^^^^^^^^ not a tuple variant or struct
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0164`.
diff --git a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr
index a8b0e3e4250..6b9e1dc7057 100644
--- a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr
+++ b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr
@@ -55,6 +55,7 @@ note: lint level defined here
 LL | #![warn(unused)] // UI tests pass `-A unused` (#43896)
    |         ^^^^^^
    = note: #[warn(unused_assignments)] implied by #[warn(unused)]
+   = help: maybe it is overwritten before being read?
 
 warning: unused variable: `fire`
   --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:54:32
diff --git a/src/test/ui/liveness/liveness-dead.stderr b/src/test/ui/liveness/liveness-dead.stderr
index 6709fee0abb..6e43cccdccf 100644
--- a/src/test/ui/liveness/liveness-dead.stderr
+++ b/src/test/ui/liveness/liveness-dead.stderr
@@ -9,24 +9,31 @@ note: lint level defined here
    |
 LL | #![deny(unused_assignments)]
    |         ^^^^^^^^^^^^^^^^^^
+   = help: maybe it is overwritten before being read?
 
 error: value assigned to `x` is never read
   --> $DIR/liveness-dead.rs:27:5
    |
 LL |     x = 4; //~ ERROR: value assigned to `x` is never read
    |     ^
+   |
+   = help: maybe it is overwritten before being read?
 
 error: value passed to `x` is never read
   --> $DIR/liveness-dead.rs:30:11
    |
 LL | fn f4(mut x: i32) { //~ ERROR: value passed to `x` is never read
    |           ^
+   |
+   = help: maybe it is overwritten before being read?
 
 error: value assigned to `x` is never read
   --> $DIR/liveness-dead.rs:37:5
    |
 LL |     x = 4; //~ ERROR: value assigned to `x` is never read
    |     ^
+   |
+   = help: maybe it is overwritten before being read?
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/liveness/liveness-unused.stderr b/src/test/ui/liveness/liveness-unused.stderr
index 2846f242fbe..35ccc79a19a 100644
--- a/src/test/ui/liveness/liveness-unused.stderr
+++ b/src/test/ui/liveness/liveness-unused.stderr
@@ -60,6 +60,7 @@ note: lint level defined here
    |
 LL | #![deny(unused_assignments)]
    |         ^^^^^^^^^^^^^^^^^^
+   = help: maybe it is overwritten before being read?
 
 error: variable `z` is assigned to, but never used
   --> $DIR/liveness-unused.rs:47:13
@@ -106,6 +107,8 @@ error: value assigned to `x` is never read
    |
 LL |         x = 0;  //~ ERROR value assigned to `x` is never read
    |         ^
+   |
+   = help: maybe it is overwritten before being read?
 
 error: aborting due to 13 previous errors
 
diff --git a/src/test/ui/nll/match-on-borrowed.rs b/src/test/ui/nll/match-on-borrowed.rs
index 6a8ce03e8fd..edce2b185df 100644
--- a/src/test/ui/nll/match-on-borrowed.rs
+++ b/src/test/ui/nll/match-on-borrowed.rs
@@ -46,9 +46,9 @@ fn enum_example(mut e: E) {
         E::V(ref mut x, _) => x,
         E::W => panic!(),
     };
-    match e { // OK, no access of borrowed data
+    match e { // Don't know that E uses a tag for its discriminant
         _ if false => (),
-        E::V(_, r) => (),
+        E::V(_, r) => (), //~ ERROR
         E::W => (),
     }
     x;
@@ -59,9 +59,9 @@ fn indirect_enum_example(mut f: &mut E) {
         E::V(ref mut x, _) => x,
         E::W => panic!(),
     };
-    match f { // OK, no access of borrowed data
+    match f { // Don't know that E uses a tag for its discriminant
         _ if false => (),
-        E::V(_, r) => (),
+        E::V(_, r) => (), //~ ERROR
         E::W => (),
     }
     x;
diff --git a/src/test/ui/nll/match-on-borrowed.stderr b/src/test/ui/nll/match-on-borrowed.stderr
index cdff29d44b8..2d34dd7805d 100644
--- a/src/test/ui/nll/match-on-borrowed.stderr
+++ b/src/test/ui/nll/match-on-borrowed.stderr
@@ -1,3 +1,27 @@
+error[E0503]: cannot use `e` because it was mutably borrowed
+  --> $DIR/match-on-borrowed.rs:51:9
+   |
+LL |         E::V(ref mut x, _) => x,
+   |              --------- borrow of `e.0` occurs here
+...
+LL |         E::V(_, r) => (), //~ ERROR
+   |         ^^^^^^^^^^ use of borrowed `e.0`
+...
+LL |     x;
+   |     - borrow later used here
+
+error[E0503]: cannot use `*f` because it was mutably borrowed
+  --> $DIR/match-on-borrowed.rs:64:9
+   |
+LL |         E::V(ref mut x, _) => x,
+   |              --------- borrow of `f.0` occurs here
+...
+LL |         E::V(_, r) => (), //~ ERROR
+   |         ^^^^^^^^^^ use of borrowed `f.0`
+...
+LL |     x;
+   |     - borrow later used here
+
 error[E0503]: cannot use `t` because it was mutably borrowed
   --> $DIR/match-on-borrowed.rs:82:9
    |
@@ -16,7 +40,7 @@ error[E0381]: use of possibly uninitialized variable: `n`
 LL |     match n {} //~ ERROR
    |           ^ use of possibly uninitialized `n`
 
-error: aborting due to 2 previous errors
+error: aborting due to 4 previous errors
 
 Some errors occurred: E0381, E0503.
 For more information about an error, try `rustc --explain E0381`.
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs
index 2a2d35e7bd9..31ec8a7dc1c 100644
--- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs
@@ -54,8 +54,14 @@ fn main() {
         simd_select(z, z, z);
         //~^ ERROR mask element type is `f32`, expected `i_`
 
+        simd_select(m4, 0u32, 1u32);
+        //~^ ERROR found non-SIMD `u32`
+
         simd_select_bitmask(0u8, x, x);
         //~^ ERROR mask length `8` != other vector length `4`
+        //
+        simd_select_bitmask(0u8, 1u32, 2u32);
+        //~^ ERROR found non-SIMD `u32`
 
         simd_select_bitmask(0.0f32, x, x);
         //~^ ERROR `f32` is not an integral type
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr
index 584f3d53921..05317da2475 100644
--- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr
@@ -16,24 +16,36 @@ error[E0511]: invalid monomorphization of `simd_select` intrinsic: mask element
 LL |         simd_select(z, z, z);
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: mismatched lengths: mask length `8` != other vector length `4`
+error[E0511]: invalid monomorphization of `simd_select` intrinsic: expected SIMD argument type, found non-SIMD `u32`
   --> $DIR/simd-intrinsic-generic-select.rs:57:9
    |
+LL |         simd_select(m4, 0u32, 1u32);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: mismatched lengths: mask length `8` != other vector length `4`
+  --> $DIR/simd-intrinsic-generic-select.rs:60:9
+   |
 LL |         simd_select_bitmask(0u8, x, x);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: expected SIMD argument type, found non-SIMD `u32`
+  --> $DIR/simd-intrinsic-generic-select.rs:63:9
+   |
+LL |         simd_select_bitmask(0u8, 1u32, 2u32);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: `f32` is not an integral type
-  --> $DIR/simd-intrinsic-generic-select.rs:60:9
+  --> $DIR/simd-intrinsic-generic-select.rs:66:9
    |
 LL |         simd_select_bitmask(0.0f32, x, x);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: `&str` is not an integral type
-  --> $DIR/simd-intrinsic-generic-select.rs:63:9
+  --> $DIR/simd-intrinsic-generic-select.rs:69:9
    |
 LL |         simd_select_bitmask("x", x, x);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 6 previous errors
+error: aborting due to 8 previous errors
 
 For more information about this error, try `rustc --explain E0511`.
diff --git a/src/test/ui/suggestions/path-display.rs b/src/test/ui/suggestions/path-display.rs
new file mode 100644
index 00000000000..62fc9e79f7a
--- /dev/null
+++ b/src/test/ui/suggestions/path-display.rs
@@ -0,0 +1,7 @@
+use std::path::Path;
+
+fn main() {
+    let path = Path::new("/tmp/foo/bar.txt");
+    println!("{}", path);
+    //~^ ERROR E0277
+}
diff --git a/src/test/ui/suggestions/path-display.stderr b/src/test/ui/suggestions/path-display.stderr
new file mode 100644
index 00000000000..39d236af4f3
--- /dev/null
+++ b/src/test/ui/suggestions/path-display.stderr
@@ -0,0 +1,14 @@
+error[E0277]: `std::path::Path` doesn't implement `std::fmt::Display`
+  --> $DIR/path-display.rs:5:20
+   |
+LL |     println!("{}", path);
+   |                    ^^^^ `std::path::Path` cannot be formatted with the default formatter; call `.display()` on it
+   |
+   = help: the trait `std::fmt::Display` is not implemented for `std::path::Path`
+   = note: call `.display()` or `.to_string_lossy()` to safely print paths, as they may contain non-Unicode data
+   = note: required because of the requirements on the impl of `std::fmt::Display` for `&std::path::Path`
+   = note: required by `std::fmt::Display::fmt`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 2b5cff6e07b..d1e4387166c 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -79,6 +79,7 @@ const WHITELIST: &[Crate] = &[
     Crate("chalk-macros"),
     Crate("cloudabi"),
     Crate("cmake"),
+    Crate("compiler_builtins"),
     Crate("crc"),
     Crate("crc32fast"),
     Crate("crossbeam-deque"),