about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-03-16 16:37:43 +0000
committerbors <bors@rust-lang.org>2021-03-16 16:37:43 +0000
commit1d6754d6eb1ac349477760a2afcd51cf75ac1a1c (patch)
treeb958b90861f439b1a0009d2cf852fa24afff63f8
parentf24ce9b0140d9be5a336954e878d0c1522966bb8 (diff)
parentec074276ab1272bb42b66407529431dfecf639a0 (diff)
downloadrust-1d6754d6eb1ac349477760a2afcd51cf75ac1a1c.tar.gz
rust-1d6754d6eb1ac349477760a2afcd51cf75ac1a1c.zip
Auto merge of #83199 - JohnTitor:rollup-zrfk94a, r=JohnTitor
Rollup of 10 pull requests

Successful merges:

 - #81822 (Added `try_exists()` method to `std::path::Path`)
 - #83072 (Update `Vec` docs)
 - #83077 (rustdoc: reduce GC work during search)
 - #83091 (Constify `copy` related functions)
 - #83156 (Fall-back to sans-serif if Arial is not available)
 - #83157 (No background for code in portability snippets)
 - #83160 (Deprecate RustcEncodable and RustcDecodable.)
 - #83162 (Specify *.woff2 files as binary)
 - #83172 (More informative diagnotic from `x.py test` attempt atop beta checkout)
 - #83196 (Use delay_span_bug instead of panic in layout_scalar_valid_range)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--.gitattributes1
-rw-r--r--compiler/rustc_middle/src/ty/context.rs15
-rw-r--r--library/alloc/src/vec/mod.rs6
-rw-r--r--library/core/src/intrinsics.rs12
-rw-r--r--library/core/src/lib.rs1
-rw-r--r--library/core/src/macros/mod.rs8
-rw-r--r--library/core/src/mem/mod.rs9
-rw-r--r--library/core/src/prelude/v1.rs2
-rw-r--r--library/core/src/ptr/const_ptr.rs6
-rw-r--r--library/core/src/ptr/mod.rs26
-rw-r--r--library/core/src/ptr/mut_ptr.rs12
-rw-r--r--library/std/src/path.rs30
-rw-r--r--library/std/src/prelude/v1.rs2
-rw-r--r--src/bootstrap/test.rs13
-rw-r--r--src/librustdoc/html/static/main.js127
-rw-r--r--src/librustdoc/html/static/rustdoc.css9
-rw-r--r--src/librustdoc/html/static/themes/ayu.css2
-rw-r--r--src/librustdoc/html/static/themes/dark.css5
-rw-r--r--src/librustdoc/html/static/themes/light.css5
-rw-r--r--src/test/ui/invalid/invalid_rustc_layout_scalar_valid_range.rs7
-rw-r--r--src/test/ui/invalid/invalid_rustc_layout_scalar_valid_range.stderr8
21 files changed, 196 insertions, 110 deletions
diff --git a/.gitattributes b/.gitattributes
index ac0a71232ef..4038db6f7da 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -8,6 +8,7 @@
 *.mir linguist-language=Rust
 src/etc/installer/gfx/* binary
 *.woff binary
+*.woff2 binary
 src/vendor/** -text
 Cargo.lock linguist-generated=false
 
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index e1d79248171..d5ad4591260 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -1091,13 +1091,16 @@ impl<'tcx> TyCtxt<'tcx> {
                 None => return Bound::Unbounded,
             };
             debug!("layout_scalar_valid_range: attr={:?}", attr);
-            for meta in attr.meta_item_list().expect("rustc_layout_scalar_valid_range takes args") {
-                match meta.literal().expect("attribute takes lit").kind {
-                    ast::LitKind::Int(a, _) => return Bound::Included(a),
-                    _ => span_bug!(attr.span, "rustc_layout_scalar_valid_range expects int arg"),
-                }
+            if let Some(
+                &[ast::NestedMetaItem::Literal(ast::Lit { kind: ast::LitKind::Int(a, _), .. })],
+            ) = attr.meta_item_list().as_deref()
+            {
+                Bound::Included(a)
+            } else {
+                self.sess
+                    .delay_span_bug(attr.span, "invalid rustc_layout_scalar_valid_range attribute");
+                Bound::Unbounded
             }
-            span_bug!(attr.span, "no arguments to `rustc_layout_scalar_valid_range` attribute");
         };
         (
             get(sym::rustc_layout_scalar_valid_range_start),
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 49758f672a8..9731a8e1d1d 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -126,7 +126,7 @@ use self::spec_extend::SpecExtend;
 
 mod spec_extend;
 
-/// A contiguous growable array type, written `Vec<T>` but pronounced 'vector'.
+/// A contiguous growable array type, written as `Vec<T>` and pronounced 'vector'.
 ///
 /// # Examples
 ///
@@ -215,7 +215,7 @@ mod spec_extend;
 ///
 /// # Slicing
 ///
-/// A `Vec` can be mutable. Slices, on the other hand, are read-only objects.
+/// A `Vec` can be mutable. On the other hand, slices are read-only objects.
 /// To get a [slice][prim@slice], use [`&`]. Example:
 ///
 /// ```
@@ -352,7 +352,7 @@ mod spec_extend;
 /// not break, however: using `unsafe` code to write to the excess capacity,
 /// and then increasing the length to match, is always valid.
 ///
-/// `Vec` does not currently guarantee the order in which elements are dropped.
+/// Currently, `Vec` does not guarantee the order in which elements are dropped.
 /// The order has changed in the past and may change again.
 ///
 /// [`get`]: ../../std/vec/struct.Vec.html#method.get
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 634ed87b091..4c2472ed82c 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -1902,18 +1902,6 @@ pub(crate) fn is_aligned_and_not_null<T>(ptr: *const T) -> bool {
     !ptr.is_null() && ptr as usize % mem::align_of::<T>() == 0
 }
 
-/// Checks whether the regions of memory starting at `src` and `dst` of size
-/// `count * size_of::<T>()` do *not* overlap.
-pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -> bool {
-    let src_usize = src as usize;
-    let dst_usize = dst as usize;
-    let size = mem::size_of::<T>().checked_mul(count).unwrap();
-    let diff = if src_usize > dst_usize { src_usize - dst_usize } else { dst_usize - src_usize };
-    // If the absolute distance between the ptrs is at least as big as the size of the buffer,
-    // they do not overlap.
-    diff >= size
-}
-
 /// Sets `count * size_of::<T>()` bytes of memory starting at `dst` to
 /// `val`.
 ///
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index e10e1738de5..8e35adcbd9e 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -98,6 +98,7 @@
 #![feature(const_slice_from_raw_parts)]
 #![feature(const_slice_ptr_len)]
 #![feature(const_size_of_val)]
+#![feature(const_swap)]
 #![feature(const_align_of_val)]
 #![feature(const_type_id)]
 #![feature(const_type_name)]
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index 28fed9b8a14..99894b5605e 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -1468,6 +1468,10 @@ pub(crate) mod builtin {
     #[rustc_builtin_macro]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[allow_internal_unstable(core_intrinsics, libstd_sys_internals)]
+    #[rustc_deprecated(
+        since = "1.52.0",
+        reason = "rustc-serialize is deprecated and no longer supported"
+    )]
     pub macro RustcDecodable($item:item) {
         /* compiler built-in */
     }
@@ -1476,6 +1480,10 @@ pub(crate) mod builtin {
     #[rustc_builtin_macro]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[allow_internal_unstable(core_intrinsics)]
+    #[rustc_deprecated(
+        since = "1.52.0",
+        reason = "rustc-serialize is deprecated and no longer supported"
+    )]
     pub macro RustcEncodable($item:item) {
         /* compiler built-in */
     }
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index 84edbd30a5d..37e8d65db6a 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -682,7 +682,8 @@ pub unsafe fn uninitialized<T>() -> T {
 /// ```
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
-pub fn swap<T>(x: &mut T, y: &mut T) {
+#[rustc_const_unstable(feature = "const_swap", issue = "83163")]
+pub const fn swap<T>(x: &mut T, y: &mut T) {
     // SAFETY: the raw pointers have been created from safe mutable references satisfying all the
     // constraints on `ptr::swap_nonoverlapping_one`
     unsafe {
@@ -812,7 +813,8 @@ pub fn take<T: Default>(dest: &mut T) -> T {
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[must_use = "if you don't need the old value, you can just assign the new value directly"]
-pub fn replace<T>(dest: &mut T, src: T) -> T {
+#[rustc_const_unstable(feature = "const_replace", issue = "83164")]
+pub const fn replace<T>(dest: &mut T, src: T) -> T {
     // SAFETY: We read from `dest` but directly write `src` into it afterwards,
     // such that the old value is not duplicated. Nothing is dropped and
     // nothing here can panic.
@@ -931,7 +933,8 @@ pub fn drop<T>(_x: T) {}
 /// ```
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
-pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
+#[rustc_const_unstable(feature = "const_transmute_copy", issue = "83165")]
+pub const unsafe fn transmute_copy<T, U>(src: &T) -> U {
     // If U has a higher alignment requirement, src may not be suitably aligned.
     if align_of::<U>() > align_of::<T>() {
         // SAFETY: `src` is a reference which is guaranteed to be valid for reads.
diff --git a/library/core/src/prelude/v1.rs b/library/core/src/prelude/v1.rs
index c7cb2a69ff7..7d33ca8bb69 100644
--- a/library/core/src/prelude/v1.rs
+++ b/library/core/src/prelude/v1.rs
@@ -61,7 +61,7 @@ pub use crate::{
 };
 
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
-#[allow(deprecated)]
+#[allow(deprecated, deprecated_in_future)]
 #[doc(no_inline)]
 pub use crate::macros::builtin::{
     bench, global_allocator, test, test_case, RustcDecodable, RustcEncodable,
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index 62ca07fc5a4..b511466acd6 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -819,9 +819,10 @@ impl<T: ?Sized> *const T {
     /// See [`ptr::copy`] for safety concerns and examples.
     ///
     /// [`ptr::copy`]: crate::ptr::copy()
+    #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
-    pub unsafe fn copy_to(self, dest: *mut T, count: usize)
+    pub const unsafe fn copy_to(self, dest: *mut T, count: usize)
     where
         T: Sized,
     {
@@ -837,9 +838,10 @@ impl<T: ?Sized> *const T {
     /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples.
     ///
     /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping()
+    #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
-    pub unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize)
+    pub const unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize)
     where
         T: Sized,
     {
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index 5ac260fc883..3a27f01444b 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -67,7 +67,7 @@
 use crate::cmp::Ordering;
 use crate::fmt;
 use crate::hash;
-use crate::intrinsics::{self, abort, is_aligned_and_not_null, is_nonoverlapping};
+use crate::intrinsics::{self, abort, is_aligned_and_not_null};
 use crate::mem::{self, MaybeUninit};
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -394,7 +394,8 @@ pub const fn slice_from_raw_parts_mut<T>(data: *mut T, len: usize) -> *mut [T] {
 /// ```
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
-pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
+#[rustc_const_unstable(feature = "const_swap", issue = "83163")]
+pub const unsafe fn swap<T>(x: *mut T, y: *mut T) {
     // Give ourselves some scratch space to work with.
     // We do not have to worry about drops: `MaybeUninit` does nothing when dropped.
     let mut tmp = MaybeUninit::<T>::uninit();
@@ -451,16 +452,8 @@ pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
 /// ```
 #[inline]
 #[stable(feature = "swap_nonoverlapping", since = "1.27.0")]
-pub unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
-    if cfg!(debug_assertions)
-        && !(is_aligned_and_not_null(x)
-            && is_aligned_and_not_null(y)
-            && is_nonoverlapping(x, y, count))
-    {
-        // Not panicking to keep codegen impact smaller.
-        abort();
-    }
-
+#[rustc_const_unstable(feature = "const_swap", issue = "83163")]
+pub const unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
     let x = x as *mut u8;
     let y = y as *mut u8;
     let len = mem::size_of::<T>() * count;
@@ -470,7 +463,8 @@ pub unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
 }
 
 #[inline]
-pub(crate) unsafe fn swap_nonoverlapping_one<T>(x: *mut T, y: *mut T) {
+#[rustc_const_unstable(feature = "const_swap", issue = "83163")]
+pub(crate) const unsafe fn swap_nonoverlapping_one<T>(x: *mut T, y: *mut T) {
     // For types smaller than the block optimization below,
     // just swap directly to avoid pessimizing codegen.
     if mem::size_of::<T>() < 32 {
@@ -488,7 +482,8 @@ pub(crate) unsafe fn swap_nonoverlapping_one<T>(x: *mut T, y: *mut T) {
 }
 
 #[inline]
-unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) {
+#[rustc_const_unstable(feature = "const_swap", issue = "83163")]
+const unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) {
     // The approach here is to utilize simd to swap x & y efficiently. Testing reveals
     // that swapping either 32 bytes or 64 bytes at a time is most efficient for Intel
     // Haswell E processors. LLVM is more able to optimize if we give a struct a
@@ -589,7 +584,8 @@ unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) {
 /// ```
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
-pub unsafe fn replace<T>(dst: *mut T, mut src: T) -> T {
+#[rustc_const_unstable(feature = "const_replace", issue = "83164")]
+pub const unsafe fn replace<T>(dst: *mut T, mut src: T) -> T {
     // SAFETY: the caller must guarantee that `dst` is valid to be
     // cast to a mutable reference (valid for writes, aligned, initialized),
     // and cannot overlap `src` since `dst` must point to a distinct
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index a365b66d8fc..fa09cf85435 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -926,9 +926,10 @@ impl<T: ?Sized> *mut T {
     /// See [`ptr::copy`] for safety concerns and examples.
     ///
     /// [`ptr::copy`]: crate::ptr::copy()
+    #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
-    pub unsafe fn copy_to(self, dest: *mut T, count: usize)
+    pub const unsafe fn copy_to(self, dest: *mut T, count: usize)
     where
         T: Sized,
     {
@@ -944,9 +945,10 @@ impl<T: ?Sized> *mut T {
     /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples.
     ///
     /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping()
+    #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
-    pub unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize)
+    pub const unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize)
     where
         T: Sized,
     {
@@ -962,9 +964,10 @@ impl<T: ?Sized> *mut T {
     /// See [`ptr::copy`] for safety concerns and examples.
     ///
     /// [`ptr::copy`]: crate::ptr::copy()
+    #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
-    pub unsafe fn copy_from(self, src: *const T, count: usize)
+    pub const unsafe fn copy_from(self, src: *const T, count: usize)
     where
         T: Sized,
     {
@@ -980,9 +983,10 @@ impl<T: ?Sized> *mut T {
     /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples.
     ///
     /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping()
+    #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
-    pub unsafe fn copy_from_nonoverlapping(self, src: *const T, count: usize)
+    pub const unsafe fn copy_from_nonoverlapping(self, src: *const T, count: usize)
     where
         T: Sized,
     {
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index de3b57df44e..57c892f32b1 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -2472,6 +2472,36 @@ impl Path {
         fs::metadata(self).is_ok()
     }
 
+    /// Returns `Ok(true)` if the path points at an existing entity.
+    ///
+    /// This function will traverse symbolic links to query information about the
+    /// destination file. In case of broken symbolic links this will return `Ok(false)`.
+    ///
+    /// As opposed to the `exists()` method, this one doesn't silently ignore errors
+    /// unrelated to the path not existing. (E.g. it will return `Err(_)` in case of permission
+    /// denied on some of the parent directories.)
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(path_try_exists)]
+    ///
+    /// use std::path::Path;
+    /// assert!(!Path::new("does_not_exist.txt").try_exists().expect("Can't check existence of file does_not_exist.txt"));
+    /// assert!(Path::new("/root/secret_file.txt").try_exists().is_err());
+    /// ```
+    // FIXME: stabilization should modify documentation of `exists()` to recommend this method
+    // instead.
+    #[unstable(feature = "path_try_exists", issue = "83186")]
+    #[inline]
+    pub fn try_exists(&self) -> io::Result<bool> {
+        match fs::metadata(self) {
+            Ok(_) => Ok(true),
+            Err(error) if error.kind() == io::ErrorKind::NotFound => Ok(false),
+            Err(error) => Err(error),
+        }
+    }
+
     /// Returns `true` if the path exists on disk and is pointing at a regular file.
     ///
     /// This function will traverse symbolic links to query information about the
diff --git a/library/std/src/prelude/v1.rs b/library/std/src/prelude/v1.rs
index ec89bb6d2a4..c5b871edbf2 100644
--- a/library/std/src/prelude/v1.rs
+++ b/library/std/src/prelude/v1.rs
@@ -48,7 +48,7 @@ pub use core::prelude::v1::{
 // FIXME: Attribute and internal derive macros are not documented because for them rustdoc generates
 // dead links which fail link checker testing.
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
-#[allow(deprecated)]
+#[allow(deprecated, deprecated_in_future)]
 #[doc(hidden)]
 pub use core::prelude::v1::{
     bench, global_allocator, test, test_case, RustcDecodable, RustcEncodable,
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 5d836c6bb62..86d940cd733 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -791,6 +791,19 @@ impl Step for Tidy {
 
         if builder.config.channel == "dev" || builder.config.channel == "nightly" {
             builder.info("fmt check");
+            if builder.config.initial_rustfmt.is_none() {
+                let inferred_rustfmt_dir = builder.config.initial_rustc.parent().unwrap();
+                eprintln!(
+                    "\
+error: no `rustfmt` binary found in {PATH}
+info: `rust.channel` is currently set to \"{CHAN}\"
+help: if you are testing a beta branch, set `rust.channel` to \"beta\" in the `config.toml` file
+help: to skip test's attempt to check tidiness, pass `--exclude src/tools/tidy` to `x.py test`",
+                    PATH = inferred_rustfmt_dir.display(),
+                    CHAN = builder.config.channel,
+                );
+                std::process::exit(1);
+            }
             crate::format::format(&builder.build, !builder.config.cmd.bless());
         }
     }
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index e8e4e21d70b..e7b522093c7 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -833,39 +833,52 @@ function defocusSearchBar() {
                 };
             }
 
-            function getObjectFromId(id) {
+            function getObjectNameFromId(id) {
                 if (typeof id === "number") {
-                    return searchIndex[id];
+                    return searchIndex[id].name;
                 }
-                return {'name': id};
+                return id;
             }
 
             function checkGenerics(obj, val) {
                 // The names match, but we need to be sure that all generics kinda
                 // match as well.
+                var tmp_lev, elem_name;
                 if (val.generics.length > 0) {
                     if (obj.length > GENERICS_DATA &&
                           obj[GENERICS_DATA].length >= val.generics.length) {
-                        var elems = obj[GENERICS_DATA].slice(0);
+                        var elems = Object.create(null);
+                        var elength = object[GENERICS_DATA].length;
+                        for (var x = 0; x < elength; ++x) {
+                            elems[getObjectNameFromId(obj[GENERICS_DATA][x])] += 1;
+                        }
                         var total = 0;
                         var done = 0;
                         // We need to find the type that matches the most to remove it in order
                         // to move forward.
                         var vlength = val.generics.length;
-                        for (var y = 0; y < vlength; ++y) {
-                            var lev = { pos: -1, lev: MAX_LEV_DISTANCE + 1};
-                            var firstGeneric = getObjectFromId(val.generics[y]).name;
-                            for (var x = 0, elength = elems.length; x < elength; ++x) {
-                                var tmp_lev = levenshtein(getObjectFromId(elems[x]).name,
-                                                                          firstGeneric);
-                                if (tmp_lev < lev.lev) {
-                                    lev.lev = tmp_lev;
-                                    lev.pos = x;
+                        for (x = 0; x < vlength; ++x) {
+                            var lev = MAX_LEV_DISTANCE + 1;
+                            var firstGeneric = getObjectNameFromId(val.generics[x]);
+                            var match = null;
+                            if (elems[firstGeneric]) {
+                                match = firstGeneric;
+                                lev = 0;
+                            } else {
+                                for (elem_name in elems) {
+                                    tmp_lev = levenshtein(elem_name, firstGeneric);
+                                    if (tmp_lev < lev) {
+                                        lev = tmp_lev;
+                                        match = elem_name;
+                                    }
                                 }
                             }
-                            if (lev.pos !== -1) {
-                                elems.splice(lev.pos, 1);
-                                total += lev.lev;
+                            if (match !== null) {
+                                elems[match] -= 1;
+                                if (elems[match] == 0) {
+                                    delete elems[match];
+                                }
+                                total += lev;
                                 done += 1;
                             } else {
                                 return MAX_LEV_DISTANCE + 1;
@@ -880,25 +893,27 @@ function defocusSearchBar() {
             // Check for type name and type generics (if any).
             function checkType(obj, val, literalSearch) {
                 var lev_distance = MAX_LEV_DISTANCE + 1;
-                var len, x, y, e_len, firstGeneric;
+                var len, x, firstGeneric;
                 if (obj[NAME] === val.name) {
                     if (literalSearch === true) {
                         if (val.generics && val.generics.length !== 0) {
                             if (obj.length > GENERICS_DATA &&
                                   obj[GENERICS_DATA].length >= val.generics.length) {
-                                var elems = obj[GENERICS_DATA].slice(0);
-                                var allFound = true;
+                                var elems = Object.create(null);
+                                len = obj[GENERICS_DATA].length;
+                                for (x = 0; x < len; ++x) {
+                                    elems[getObjectNameFromId(obj[GENERICS_DATA][x])] += 1;
+                                }
 
+                                var allFound = true;
                                 len = val.generics.length;
-                                for (y = 0; allFound === true && y < len; ++y) {
-                                    allFound = false;
-                                    firstGeneric = getObjectFromId(val.generics[y]).name;
-                                    e_len = elems.length;
-                                    for (x = 0; allFound === false && x < e_len; ++x) {
-                                        allFound = getObjectFromId(elems[x]).name === firstGeneric;
-                                    }
-                                    if (allFound === true) {
-                                        elems.splice(x - 1, 1);
+                                for (x = 0; x < len; ++x) {
+                                    firstGeneric = getObjectNameFromId(val.generics[x]);
+                                    if (elems[firstGeneric]) {
+                                        elems[firstGeneric] -= 1;
+                                    } else {
+                                        allFound = false;
+                                        break;
                                     }
                                 }
                                 if (allFound === true) {
@@ -1066,13 +1081,6 @@ function defocusSearchBar() {
                 return false;
             }
 
-            function generateId(ty) {
-                if (ty.parent && ty.parent.name) {
-                    return itemTypes[ty.ty] + ty.path + ty.parent.name + ty.name;
-                }
-                return itemTypes[ty.ty] + ty.path + ty.name;
-            }
-
             function createAliasFromItem(item) {
                 return {
                     crate: item.crate,
@@ -1158,7 +1166,7 @@ function defocusSearchBar() {
                     in_args = findArg(searchIndex[i], val, true, typeFilter);
                     returned = checkReturned(searchIndex[i], val, true, typeFilter);
                     ty = searchIndex[i];
-                    fullId = generateId(ty);
+                    fullId = ty.id;
 
                     if (searchWords[i] === val.name
                         && typePassesFilter(typeFilter, searchIndex[i].ty)
@@ -1208,7 +1216,7 @@ function defocusSearchBar() {
                     if (!type) {
                         continue;
                     }
-                    fullId = generateId(ty);
+                    fullId = ty.id;
 
                     returned = checkReturned(ty, output, true, NO_TYPE_FILTER);
                     if (output.name === "*" || returned === true) {
@@ -1292,15 +1300,15 @@ function defocusSearchBar() {
                     var index = -1;
                     // we want lev results to go lower than others
                     lev = MAX_LEV_DISTANCE + 1;
-                    fullId = generateId(ty);
+                    fullId = ty.id;
 
                     if (searchWords[j].indexOf(split[i]) > -1 ||
                         searchWords[j].indexOf(val) > -1 ||
-                        searchWords[j].replace(/_/g, "").indexOf(val) > -1)
+                        ty.normalizedName.indexOf(val) > -1)
                     {
                         // filter type: ... queries
                         if (typePassesFilter(typeFilter, ty.ty) && results[fullId] === undefined) {
-                            index = searchWords[j].replace(/_/g, "").indexOf(val);
+                            index = ty.normalizedName.indexOf(val);
                         }
                     }
                     if ((lev = levenshtein(searchWords[j], val)) <= MAX_LEV_DISTANCE) {
@@ -1828,8 +1836,9 @@ function defocusSearchBar() {
         function buildIndex(rawSearchIndex) {
             searchIndex = [];
             var searchWords = [];
-            var i;
+            var i, word;
             var currentIndex = 0;
+            var id = 0;
 
             for (var crate in rawSearchIndex) {
                 if (!hasOwnProperty(rawSearchIndex, crate)) { continue; }
@@ -1837,14 +1846,25 @@ function defocusSearchBar() {
                 var crateSize = 0;
 
                 searchWords.push(crate);
-                searchIndex.push({
+                var normalizedName = crate.indexOf("_") === -1
+                    ? crate
+                    : crate.replace(/_/g, "");
+                // This object should have exactly the same set of fields as the "row"
+                // object defined below. Your JavaScript runtime will thank you.
+                // https://mathiasbynens.be/notes/shapes-ics
+                var crateRow = {
                     crate: crate,
                     ty: 1, // == ExternCrate
                     name: crate,
                     path: "",
                     desc: rawSearchIndex[crate].doc,
+                    parent: undefined,
                     type: null,
-                });
+                    id: id,
+                    normalizedName: normalizedName,
+                };
+                id += 1;
+                searchIndex.push(crateRow);
                 currentIndex += 1;
 
                 // an array of (Number) item types
@@ -1882,6 +1902,18 @@ function defocusSearchBar() {
                 len = itemTypes.length;
                 var lastPath = "";
                 for (i = 0; i < len; ++i) {
+                    // This object should have exactly the same set of fields as the "crateRow"
+                    // object defined above.
+                    if (typeof itemNames[i] === "string") {
+                        word = itemNames[i].toLowerCase();
+                        searchWords.push(word);
+                    } else {
+                        word = "";
+                        searchWords.push("");
+                    }
+                    var normalizedName = word.indexOf("_") === -1
+                        ? word
+                        : word.replace(/_/g, "");
                     var row = {
                         crate: crate,
                         ty: itemTypes[i],
@@ -1890,14 +1922,11 @@ function defocusSearchBar() {
                         desc: itemDescs[i],
                         parent: itemParentIdxs[i] > 0 ? paths[itemParentIdxs[i] - 1] : undefined,
                         type: itemFunctionSearchTypes[i],
+                        id: id,
+                        normalizedName: normalizedName,
                     };
+                    id += 1;
                     searchIndex.push(row);
-                    if (typeof row.name === "string") {
-                        var word = row.name.toLowerCase();
-                        searchWords.push(word);
-                    } else {
-                        searchWords.push("");
-                    }
                     lastPath = row.path;
                     crateSize += 1;
                 }
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index 27f1ea78ad2..4f287cde73b 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -136,11 +136,12 @@ h1, h2, h3, h4,
 #source-sidebar, #sidebar-toggle,
 /* This selector is for the items listed in the "all items" page. */
 #main > ul.docblock > li > a {
-	font-family: "Fira Sans", Arial;
+	font-family: "Fira Sans", Arial, sans-serif;
 }
 
 .content ul.crate a.crate {
-	font: 16px/1.6 "Fira Sans";
+	font-size: 16px/1.6;
+	font-family: "Fira Sans", Arial, sans-serif;
 }
 
 ol, ul {
@@ -482,7 +483,7 @@ h4 > code, h3 > code, .invisible > code {
 }
 #main > .since {
 	top: inherit;
-	font-family: "Fira Sans", Arial;
+	font-family: "Fira Sans", Arial, sans-serif;
 }
 
 .content table:not(.table-display) {
@@ -1301,7 +1302,7 @@ h4 > .notable-traits {
 
 .help-button {
 	right: 30px;
-	font-family: "Fira Sans", Arial;
+	font-family: "Fira Sans", Arial, sans-serif;
 	text-align: center;
 	font-size: 17px;
 }
diff --git a/src/librustdoc/html/static/themes/ayu.css b/src/librustdoc/html/static/themes/ayu.css
index fd8153519af..7374aee71f8 100644
--- a/src/librustdoc/html/static/themes/ayu.css
+++ b/src/librustdoc/html/static/themes/ayu.css
@@ -266,7 +266,7 @@ a {
 
 .stab.portability > code {
 	color: #e6e1cf;
-	background-color: transparent;
+	background: none;
 }
 
 #help > div {
diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css
index 9eeccd038a2..88ac3252bb4 100644
--- a/src/librustdoc/html/static/themes/dark.css
+++ b/src/librustdoc/html/static/themes/dark.css
@@ -222,10 +222,7 @@ a.test-arrow {
 .stab.unstable { background: #FFF5D6; border-color: #FFC600; color: #2f2f2f; }
 .stab.deprecated { background: #F3DFFF; border-color: #7F0087; color: #2f2f2f; }
 .stab.portability { background: #C4ECFF; border-color: #7BA5DB; color: #2f2f2f; }
-
-.stab.portability > code {
-	color: #ddd;
-}
+.stab.portability > code { background: none; }
 
 #help > div {
 	background: #4d4d4d;
diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css
index 814043b35ae..9bc21102aaa 100644
--- a/src/librustdoc/html/static/themes/light.css
+++ b/src/librustdoc/html/static/themes/light.css
@@ -220,10 +220,7 @@ a.test-arrow {
 .stab.unstable { background: #FFF5D6; border-color: #FFC600; }
 .stab.deprecated { background: #F3DFFF; border-color: #7F0087; }
 .stab.portability { background: #C4ECFF; border-color: #7BA5DB; }
-
-.stab.portability > code {
-	color: #000;
-}
+.stab.portability > code { background: none; }
 
 #help > div {
 	background: #e9e9e9;
diff --git a/src/test/ui/invalid/invalid_rustc_layout_scalar_valid_range.rs b/src/test/ui/invalid/invalid_rustc_layout_scalar_valid_range.rs
index 25fe4be660b..06cf8c0f0f6 100644
--- a/src/test/ui/invalid/invalid_rustc_layout_scalar_valid_range.rs
+++ b/src/test/ui/invalid/invalid_rustc_layout_scalar_valid_range.rs
@@ -15,6 +15,13 @@ enum E {
     Y = 14,
 }
 
+#[rustc_layout_scalar_valid_range_start(rustc_layout_scalar_valid_range_start)] //~ ERROR
+struct NonZero<T>(T);
+
+fn not_field() -> impl Send {
+    NonZero(false)
+}
+
 fn main() {
     let _ = A(0);
     let _ = B(0);
diff --git a/src/test/ui/invalid/invalid_rustc_layout_scalar_valid_range.stderr b/src/test/ui/invalid/invalid_rustc_layout_scalar_valid_range.stderr
index 7e95fedebdf..7879e7358c0 100644
--- a/src/test/ui/invalid/invalid_rustc_layout_scalar_valid_range.stderr
+++ b/src/test/ui/invalid/invalid_rustc_layout_scalar_valid_range.stderr
@@ -27,5 +27,11 @@ LL | |     Y = 14,
 LL | | }
    | |_- not a struct
 
-error: aborting due to 4 previous errors
+error: expected exactly one integer literal argument
+  --> $DIR/invalid_rustc_layout_scalar_valid_range.rs:18:1
+   |
+LL | #[rustc_layout_scalar_valid_range_start(rustc_layout_scalar_valid_range_start)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors