From ea5843cc7781dd572679c69fd008bfe71279b03d Mon Sep 17 00:00:00 2001
From: Andy Russell <arussell123@gmail.com>
Date: Fri, 16 Nov 2018 14:30:52 -0500
Subject: [PATCH 01/45] fix intra-link resolution spans in block comments

This commit improves the calculation of code spans for intra-doc
resolution failures. All sugared doc comments should now have the
correct spans, including those where the comment is longer than the
docs.

It also fixes an issue where the spans were calculated incorrectly for
certain unsugared doc comments. The diagnostic will now always use the
span of the attributes, as originally intended.

Fixes #55964.
---
 src/librustdoc/clean/mod.rs                   |  2 -
 .../passes/collect_intra_doc_links.rs         | 81 ++++++++++++------
 src/test/rustdoc-ui/intra-links-warning.rs    | 23 +++++
 .../rustdoc-ui/intra-links-warning.stderr     | 84 +++++++++++++------
 4 files changed, 140 insertions(+), 50 deletions(-)

diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 0518d73e1e30f..50b17f59b47d9 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -708,8 +708,6 @@ impl<I: IntoIterator<Item=ast::NestedMetaItem>> NestedAttributesExt for I {
 /// kept separate because of issue #42760.
 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
 pub enum DocFragment {
-    // FIXME #44229 (misdreavus): sugared and raw doc comments can be brought back together once
-    // hoedown is completely removed from rustdoc.
     /// A doc fragment created from a `///` or `//!` doc comment.
     SugaredDoc(usize, syntax_pos::Span, String),
     /// A doc fragment created from a "raw" `#[doc=""]` attribute.
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index f5056cead567e..31047ab353a47 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -497,6 +497,19 @@ fn span_of_attrs(attrs: &Attributes) -> syntax_pos::Span {
     start.to(end)
 }
 
+/// Reports a resolution failure diagnostic.
+///
+/// Ideally we can report the diagnostic with the actual span in the source where the link failure
+/// occurred. However, there's a mismatch between the span in the source code and the span in the
+/// markdown, so we have to do a bit of work to figure out the correspondence.
+///
+/// It's not too hard to find the span for sugared doc comments (`///` and `/**`), because the
+/// source will match the markdown exactly, excluding the comment markers. However, it's much more
+/// difficult to calculate the spans for unsugared docs, because we have to deal with escaping and
+/// other source features. So, we attempt to find the exact source span of the resolution failure
+/// in sugared docs, but use the span of the documentation attributes themselves for unsugared
+/// docs. Because this span might be overly large, we display the markdown line containing the
+/// failure as a note.
 fn resolution_failure(
     cx: &DocContext,
     attrs: &Attributes,
@@ -507,34 +520,50 @@ fn resolution_failure(
     let sp = span_of_attrs(attrs);
     let msg = format!("`[{}]` cannot be resolved, ignoring it...", path_str);
 
-    let code_dox = sp.to_src(cx);
-
-    let doc_comment_padding = 3;
     let mut diag = if let Some(link_range) = link_range {
-        // blah blah blah\nblah\nblah [blah] blah blah\nblah blah
-        //                       ^    ~~~~~~
-        //                       |    link_range
-        //                       last_new_line_offset
-
         let mut diag;
-        if dox.lines().count() == code_dox.lines().count() {
-            let line_offset = dox[..link_range.start].lines().count();
-            // The span starts in the `///`, so we don't have to account for the leading whitespace
-            let code_dox_len = if line_offset <= 1 {
-                doc_comment_padding
-            } else {
-                // The first `///`
-                doc_comment_padding +
-                    // Each subsequent leading whitespace and `///`
-                    code_dox.lines().skip(1).take(line_offset - 1).fold(0, |sum, line| {
-                        sum + doc_comment_padding + line.len() - line.trim_start().len()
-                    })
-            };
 
-            // Extract the specific span
+        if attrs.doc_strings.iter().all(|frag| match frag {
+            DocFragment::SugaredDoc(..) => true,
+            _ => false,
+        }) {
+            let source_dox = sp.to_src(cx);
+            let mut source_lines = source_dox.lines().peekable();
+            let mut md_lines = dox.lines().peekable();
+
+            // The number of bytes from the start of the source span to the resolution failure that
+            // are *not* part of the markdown, like comment markers.
+            let mut source_offset = 0;
+
+            // Eat any source lines before the markdown starts (e.g., `/**` on its own line).
+            while let Some(source_line) = source_lines.peek() {
+                if source_line.contains(md_lines.peek().unwrap()) {
+                    break;
+                }
+
+                // Include the newline.
+                source_offset += source_line.len() + 1;
+                source_lines.next().unwrap();
+            }
+
+            // The number of lines up to and including the resolution failure.
+            let num_lines = dox[..link_range.start].lines().count();
+
+            // Consume inner comment markers (e.g., `///` or ` *`).
+            for (source_line, md_line) in source_lines.zip(md_lines).take(num_lines) {
+                source_offset += if md_line.is_empty() {
+                    // If there is no markdown on this line, then the whole line is a comment
+                    // marker. We don't have to count the newline here because it's in the markdown
+                    // too.
+                    source_line.len()
+                } else {
+                    source_line.find(md_line).unwrap()
+                };
+            }
+
             let sp = sp.from_inner_byte_pos(
-                link_range.start + code_dox_len,
-                link_range.end + code_dox_len,
+                link_range.start + source_offset,
+                link_range.end + source_offset,
             );
 
             diag = cx.tcx.struct_span_lint_node(lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE,
@@ -548,6 +577,10 @@ fn resolution_failure(
                                                 sp,
                                                 &msg);
 
+            // blah blah blah\nblah\nblah [blah] blah blah\nblah blah
+            //                       ^     ~~~~
+            //                       |     link_range
+            //                       last_new_line_offset
             let last_new_line_offset = dox[..link_range.start].rfind('\n').map_or(0, |n| n + 1);
             let line = dox[last_new_line_offset..].lines().next().unwrap_or("");
 
diff --git a/src/test/rustdoc-ui/intra-links-warning.rs b/src/test/rustdoc-ui/intra-links-warning.rs
index d6bc275b57a6a..3051bec88d24d 100644
--- a/src/test/rustdoc-ui/intra-links-warning.rs
+++ b/src/test/rustdoc-ui/intra-links-warning.rs
@@ -55,3 +55,26 @@ macro_rules! f {
     }
 }
 f!("Foo\nbar [BarF] bar\nbaz");
+
+/** # for example,
+ *
+ * time to introduce a link [error]*/
+pub struct A;
+
+/**
+ * # for example,
+ *
+ * time to introduce a link [error]
+ */
+pub struct B;
+
+#[doc = "single line [error]"]
+pub struct C;
+
+#[doc = "single line with \"escaping\" [error]"]
+pub struct D;
+
+/// Item docs.
+#[doc="Hello there!"]
+/// [error]
+pub struct E;
diff --git a/src/test/rustdoc-ui/intra-links-warning.stderr b/src/test/rustdoc-ui/intra-links-warning.stderr
index c05f99fadc9e4..543919938cea7 100644
--- a/src/test/rustdoc-ui/intra-links-warning.stderr
+++ b/src/test/rustdoc-ui/intra-links-warning.stderr
@@ -55,6 +55,60 @@ LL |        /// [Qux:Y]
    |
    = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]`
 
+warning: `[error]` cannot be resolved, ignoring it...
+  --> $DIR/intra-links-warning.rs:61:30
+   |
+LL |  * time to introduce a link [error]*/
+   |                              ^^^^^ cannot be resolved, ignoring
+   |
+   = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]`
+
+warning: `[error]` cannot be resolved, ignoring it...
+  --> $DIR/intra-links-warning.rs:67:30
+   |
+LL |  * time to introduce a link [error]
+   |                              ^^^^^ cannot be resolved, ignoring
+   |
+   = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]`
+
+warning: `[error]` cannot be resolved, ignoring it...
+  --> $DIR/intra-links-warning.rs:71:1
+   |
+LL | #[doc = "single line [error]"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the link appears in this line:
+           
+           single line [error]
+                        ^^^^^
+   = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]`
+
+warning: `[error]` cannot be resolved, ignoring it...
+  --> $DIR/intra-links-warning.rs:74:1
+   |
+LL | #[doc = "single line with /"escaping/" [error]"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the link appears in this line:
+           
+           single line with "escaping" [error]
+                                        ^^^^^
+   = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]`
+
+warning: `[error]` cannot be resolved, ignoring it...
+  --> $DIR/intra-links-warning.rs:77:1
+   |
+LL | / /// Item docs.
+LL | | #[doc="Hello there!"]
+LL | | /// [error]
+   | |___________^
+   |
+   = note: the link appears in this line:
+           
+            [error]
+             ^^^^^
+   = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]`
+
 warning: `[BarA]` cannot be resolved, ignoring it...
   --> $DIR/intra-links-warning.rs:24:10
    |
@@ -64,37 +118,19 @@ LL | /// bar [BarA] bar
    = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]`
 
 warning: `[BarB]` cannot be resolved, ignoring it...
-  --> $DIR/intra-links-warning.rs:28:1
+  --> $DIR/intra-links-warning.rs:30:9
    |
-LL | / /**
-LL | |  * Foo
-LL | |  * bar [BarB] bar
-LL | |  * baz
-LL | |  */
-   | |___^
+LL |  * bar [BarB] bar
+   |         ^^^^ cannot be resolved, ignoring
    |
-   = note: the link appears in this line:
-           
-            bar [BarB] bar
-                 ^^^^
    = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]`
 
 warning: `[BarC]` cannot be resolved, ignoring it...
-  --> $DIR/intra-links-warning.rs:35:1
+  --> $DIR/intra-links-warning.rs:37:6
    |
-LL | / /** Foo
-LL | |
-LL | | bar [BarC] bar
-LL | | baz
-...  |
-LL | |
-LL | | */
-   | |__^
+LL | bar [BarC] bar
+   |      ^^^^ cannot be resolved, ignoring
    |
-   = note: the link appears in this line:
-           
-           bar [BarC] bar
-                ^^^^
    = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]`
 
 warning: `[BarD]` cannot be resolved, ignoring it...

From 700c83bc05ebeddbe3d3a10c2e309826d563b12b Mon Sep 17 00:00:00 2001
From: Bastian Gruber <gruberbastian@me.com>
Date: Sun, 24 Jun 2018 09:38:56 +0200
Subject: [PATCH 02/45] Document `From` implementations

---
 src/libstd/path.rs | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/src/libstd/path.rs b/src/libstd/path.rs
index a153456370c6f..ab37bb7520972 100644
--- a/src/libstd/path.rs
+++ b/src/libstd/path.rs
@@ -1397,6 +1397,8 @@ impl<'a> From<&'a Path> for Box<Path> {
 
 #[stable(feature = "path_buf_from_box", since = "1.18.0")]
 impl From<Box<Path>> for PathBuf {
+    /// Converts a `Box<Path>` into a `PathBuf`.
+    /// This conversion does not allocate memory
     fn from(boxed: Box<Path>) -> PathBuf {
         boxed.into_path_buf()
     }
@@ -1404,6 +1406,8 @@ impl From<Box<Path>> for PathBuf {
 
 #[stable(feature = "box_from_path_buf", since = "1.20.0")]
 impl From<PathBuf> for Box<Path> {
+    /// Converts a `PathBuf` into a `Box<Path>`.
+    /// This conversion does not allocate memory
     fn from(p: PathBuf) -> Box<Path> {
         p.into_boxed_path()
     }
@@ -1426,6 +1430,9 @@ impl<'a, T: ?Sized + AsRef<OsStr>> From<&'a T> for PathBuf {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl From<OsString> for PathBuf {
+    /// Converts a `OsString` into a `PathBuf`.
+    /// This conversion copies the data.
+    /// This conversion does allocate memory.
     fn from(s: OsString) -> PathBuf {
         PathBuf { inner: s }
     }
@@ -1433,6 +1440,9 @@ impl From<OsString> for PathBuf {
 
 #[stable(feature = "from_path_buf_for_os_string", since = "1.14.0")]
 impl From<PathBuf> for OsString {
+    /// Converts a `PathBuf` into a `OsString`.
+    /// This conversion copies the data.
+    /// This conversion does allocate memory.
     fn from(path_buf : PathBuf) -> OsString {
         path_buf.inner
     }
@@ -1440,6 +1450,8 @@ impl From<PathBuf> for OsString {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl From<String> for PathBuf {
+    /// Converts a `String` into a `PathBuf`.
+    /// This conversion does not allocate memory
     fn from(s: String) -> PathBuf {
         PathBuf::from(OsString::from(s))
     }
@@ -1536,6 +1548,10 @@ impl<'a> From<Cow<'a, Path>> for PathBuf {
 
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<PathBuf> for Arc<Path> {
+    /// Converts a `PathBuf` into a `Arc<Path>`.
+    /// This conversion happens in place.
+    /// This conversion does not allocate memory.
+    /// This function is unsafe. Data can't be moved from this reference.
     #[inline]
     fn from(s: PathBuf) -> Arc<Path> {
         let arc: Arc<OsStr> = Arc::from(s.into_os_string());
@@ -1545,6 +1561,10 @@ impl From<PathBuf> for Arc<Path> {
 
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl<'a> From<&'a Path> for Arc<Path> {
+    /// Converts a `PathBuf` into a `Arc<Path>`.
+    /// This conversion happens in place.
+    /// This conversion does not allocate memory.
+    /// This function is unsafe. Data can't be moved from this reference.
     #[inline]
     fn from(s: &Path) -> Arc<Path> {
         let arc: Arc<OsStr> = Arc::from(s.as_os_str());
@@ -1554,6 +1574,10 @@ impl<'a> From<&'a Path> for Arc<Path> {
 
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<PathBuf> for Rc<Path> {
+    /// Converts a `PathBuf` into a `Rc<Path>`.
+    /// This conversion happens in place.
+    /// This conversion does not allocate memory.
+    /// This function is unsafe. Data can't be moved from this reference.
     #[inline]
     fn from(s: PathBuf) -> Rc<Path> {
         let rc: Rc<OsStr> = Rc::from(s.into_os_string());

From 072bca3ff5a3907a71c22fba041825cfa3eb321e Mon Sep 17 00:00:00 2001
From: Bastian Gruber <gruberbastian@me.com>
Date: Mon, 25 Jun 2018 14:24:39 +0200
Subject: [PATCH 03/45] Remove 'unsafe' comments

---
 src/libstd/path.rs | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/src/libstd/path.rs b/src/libstd/path.rs
index ab37bb7520972..9145eeb6063f6 100644
--- a/src/libstd/path.rs
+++ b/src/libstd/path.rs
@@ -1551,7 +1551,6 @@ impl From<PathBuf> for Arc<Path> {
     /// Converts a `PathBuf` into a `Arc<Path>`.
     /// This conversion happens in place.
     /// This conversion does not allocate memory.
-    /// This function is unsafe. Data can't be moved from this reference.
     #[inline]
     fn from(s: PathBuf) -> Arc<Path> {
         let arc: Arc<OsStr> = Arc::from(s.into_os_string());
@@ -1564,7 +1563,6 @@ impl<'a> From<&'a Path> for Arc<Path> {
     /// Converts a `PathBuf` into a `Arc<Path>`.
     /// This conversion happens in place.
     /// This conversion does not allocate memory.
-    /// This function is unsafe. Data can't be moved from this reference.
     #[inline]
     fn from(s: &Path) -> Arc<Path> {
         let arc: Arc<OsStr> = Arc::from(s.as_os_str());
@@ -1577,7 +1575,6 @@ impl From<PathBuf> for Rc<Path> {
     /// Converts a `PathBuf` into a `Rc<Path>`.
     /// This conversion happens in place.
     /// This conversion does not allocate memory.
-    /// This function is unsafe. Data can't be moved from this reference.
     #[inline]
     fn from(s: PathBuf) -> Rc<Path> {
         let rc: Rc<OsStr> = Rc::from(s.into_os_string());

From 88a708dd6a5bb14f3a19ae98238ddf2d03cb93d3 Mon Sep 17 00:00:00 2001
From: Bastian Gruber <gruberbastian@me.com>
Date: Mon, 25 Jun 2018 21:29:22 +0200
Subject: [PATCH 04/45] Update comments

---
 src/libstd/path.rs | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/src/libstd/path.rs b/src/libstd/path.rs
index 9145eeb6063f6..e631bb90f5741 100644
--- a/src/libstd/path.rs
+++ b/src/libstd/path.rs
@@ -1431,8 +1431,7 @@ impl<'a, T: ?Sized + AsRef<OsStr>> From<&'a T> for PathBuf {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl From<OsString> for PathBuf {
     /// Converts a `OsString` into a `PathBuf`.
-    /// This conversion copies the data.
-    /// This conversion does allocate memory.
+    /// This conversion does not allocate memory
     fn from(s: OsString) -> PathBuf {
         PathBuf { inner: s }
     }
@@ -1441,8 +1440,7 @@ impl From<OsString> for PathBuf {
 #[stable(feature = "from_path_buf_for_os_string", since = "1.14.0")]
 impl From<PathBuf> for OsString {
     /// Converts a `PathBuf` into a `OsString`.
-    /// This conversion copies the data.
-    /// This conversion does allocate memory.
+    /// This conversion does not allocate memory
     fn from(path_buf : PathBuf) -> OsString {
         path_buf.inner
     }

From 5c747eb32654401b9b6fe053c3f51399a6454f8c Mon Sep 17 00:00:00 2001
From: Bastian Gruber <gruberbastian@me.com>
Date: Thu, 26 Jul 2018 10:59:46 +0200
Subject: [PATCH 05/45] Update style of comments

---
 src/libstd/path.rs | 40 ++++++++++++++++++++++++++--------------
 1 file changed, 26 insertions(+), 14 deletions(-)

diff --git a/src/libstd/path.rs b/src/libstd/path.rs
index e631bb90f5741..9f6fcad242292 100644
--- a/src/libstd/path.rs
+++ b/src/libstd/path.rs
@@ -1397,7 +1397,8 @@ impl<'a> From<&'a Path> for Box<Path> {
 
 #[stable(feature = "path_buf_from_box", since = "1.18.0")]
 impl From<Box<Path>> for PathBuf {
-    /// Converts a `Box<Path>` into a `PathBuf`.
+    /// Converts a `Box<Path>` into a `PathBuf`
+    ///
     /// This conversion does not allocate memory
     fn from(boxed: Box<Path>) -> PathBuf {
         boxed.into_path_buf()
@@ -1406,7 +1407,8 @@ impl From<Box<Path>> for PathBuf {
 
 #[stable(feature = "box_from_path_buf", since = "1.20.0")]
 impl From<PathBuf> for Box<Path> {
-    /// Converts a `PathBuf` into a `Box<Path>`.
+    /// Converts a `PathBuf` into a `Box<Path>`
+    ///
     /// This conversion does not allocate memory
     fn from(p: PathBuf) -> Box<Path> {
         p.into_boxed_path()
@@ -1430,7 +1432,8 @@ impl<'a, T: ?Sized + AsRef<OsStr>> From<&'a T> for PathBuf {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl From<OsString> for PathBuf {
-    /// Converts a `OsString` into a `PathBuf`.
+    /// Converts a `OsString` into a `PathBuf`
+    ///
     /// This conversion does not allocate memory
     fn from(s: OsString) -> PathBuf {
         PathBuf { inner: s }
@@ -1439,7 +1442,8 @@ impl From<OsString> for PathBuf {
 
 #[stable(feature = "from_path_buf_for_os_string", since = "1.14.0")]
 impl From<PathBuf> for OsString {
-    /// Converts a `PathBuf` into a `OsString`.
+    /// Converts a `PathBuf` into a `OsString`
+    ///
     /// This conversion does not allocate memory
     fn from(path_buf : PathBuf) -> OsString {
         path_buf.inner
@@ -1448,7 +1452,8 @@ impl From<PathBuf> for OsString {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl From<String> for PathBuf {
-    /// Converts a `String` into a `PathBuf`.
+    /// Converts a `String` into a `PathBuf`
+    ///
     /// This conversion does not allocate memory
     fn from(s: String) -> PathBuf {
         PathBuf::from(OsString::from(s))
@@ -1546,9 +1551,11 @@ impl<'a> From<Cow<'a, Path>> for PathBuf {
 
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<PathBuf> for Arc<Path> {
-    /// Converts a `PathBuf` into a `Arc<Path>`.
-    /// This conversion happens in place.
-    /// This conversion does not allocate memory.
+    /// Converts a `PathBuf` into a `Arc<Path>`
+    ///
+    /// This conversion happens in place
+    ///
+    /// This conversion does not allocate memory
     #[inline]
     fn from(s: PathBuf) -> Arc<Path> {
         let arc: Arc<OsStr> = Arc::from(s.into_os_string());
@@ -1558,9 +1565,12 @@ impl From<PathBuf> for Arc<Path> {
 
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl<'a> From<&'a Path> for Arc<Path> {
-    /// Converts a `PathBuf` into a `Arc<Path>`.
-    /// This conversion happens in place.
-    /// This conversion does not allocate memory.
+    /// Converts a `PathBuf` into a `Arc<Path>`
+    ///
+    /// This conversion happens in place
+    ///
+    /// This conversion does not allocate memory
+    ///
     #[inline]
     fn from(s: &Path) -> Arc<Path> {
         let arc: Arc<OsStr> = Arc::from(s.as_os_str());
@@ -1570,9 +1580,11 @@ impl<'a> From<&'a Path> for Arc<Path> {
 
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<PathBuf> for Rc<Path> {
-    /// Converts a `PathBuf` into a `Rc<Path>`.
-    /// This conversion happens in place.
-    /// This conversion does not allocate memory.
+    /// Converts a `PathBuf` into a `Rc<Path>`
+    ///
+    /// This conversion happens in place
+    ///
+    /// This conversion does not allocate memory
     #[inline]
     fn from(s: PathBuf) -> Rc<Path> {
         let rc: Rc<OsStr> = Rc::from(s.into_os_string());

From e8dafbaf10bf9e54854382f0aa830d219aec85bb Mon Sep 17 00:00:00 2001
From: Bastian Gruber <gruberbastian@me.com>
Date: Wed, 21 Nov 2018 13:06:22 +0100
Subject: [PATCH 06/45] Adjust doc comments

---
 src/libstd/path.rs | 31 ++++++++++---------------------
 1 file changed, 10 insertions(+), 21 deletions(-)

diff --git a/src/libstd/path.rs b/src/libstd/path.rs
index 9f6fcad242292..2d0a2501f7e99 100644
--- a/src/libstd/path.rs
+++ b/src/libstd/path.rs
@@ -1399,7 +1399,7 @@ impl<'a> From<&'a Path> for Box<Path> {
 impl From<Box<Path>> for PathBuf {
     /// Converts a `Box<Path>` into a `PathBuf`
     ///
-    /// This conversion does not allocate memory
+    /// This conversion does not allocate or copy memory.
     fn from(boxed: Box<Path>) -> PathBuf {
         boxed.into_path_buf()
     }
@@ -1409,7 +1409,8 @@ impl From<Box<Path>> for PathBuf {
 impl From<PathBuf> for Box<Path> {
     /// Converts a `PathBuf` into a `Box<Path>`
     ///
-    /// This conversion does not allocate memory
+    /// This conversion currently should not allocate memory, 
+    // but this behavior is not guaranteed on all platforms or in all future versions.
     fn from(p: PathBuf) -> Box<Path> {
         p.into_boxed_path()
     }
@@ -1434,7 +1435,7 @@ impl<'a, T: ?Sized + AsRef<OsStr>> From<&'a T> for PathBuf {
 impl From<OsString> for PathBuf {
     /// Converts a `OsString` into a `PathBuf`
     ///
-    /// This conversion does not allocate memory
+    /// This conversion does not allocate or copy memory.
     fn from(s: OsString) -> PathBuf {
         PathBuf { inner: s }
     }
@@ -1444,7 +1445,7 @@ impl From<OsString> for PathBuf {
 impl From<PathBuf> for OsString {
     /// Converts a `PathBuf` into a `OsString`
     ///
-    /// This conversion does not allocate memory
+    /// This conversion does not allocate or copy memory.
     fn from(path_buf : PathBuf) -> OsString {
         path_buf.inner
     }
@@ -1454,7 +1455,7 @@ impl From<PathBuf> for OsString {
 impl From<String> for PathBuf {
     /// Converts a `String` into a `PathBuf`
     ///
-    /// This conversion does not allocate memory
+    /// This conversion does not allocate or copy memory.
     fn from(s: String) -> PathBuf {
         PathBuf::from(OsString::from(s))
     }
@@ -1551,11 +1552,7 @@ impl<'a> From<Cow<'a, Path>> for PathBuf {
 
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<PathBuf> for Arc<Path> {
-    /// Converts a `PathBuf` into a `Arc<Path>`
-    ///
-    /// This conversion happens in place
-    ///
-    /// This conversion does not allocate memory
+    /// Converts a Path into a Rc by copying the Path data into a new Rc buffer.
     #[inline]
     fn from(s: PathBuf) -> Arc<Path> {
         let arc: Arc<OsStr> = Arc::from(s.into_os_string());
@@ -1565,12 +1562,7 @@ impl From<PathBuf> for Arc<Path> {
 
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl<'a> From<&'a Path> for Arc<Path> {
-    /// Converts a `PathBuf` into a `Arc<Path>`
-    ///
-    /// This conversion happens in place
-    ///
-    /// This conversion does not allocate memory
-    ///
+    /// Converts a Path into a Rc by copying the Path data into a new Rc buffer.
     #[inline]
     fn from(s: &Path) -> Arc<Path> {
         let arc: Arc<OsStr> = Arc::from(s.as_os_str());
@@ -1580,11 +1572,7 @@ impl<'a> From<&'a Path> for Arc<Path> {
 
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<PathBuf> for Rc<Path> {
-    /// Converts a `PathBuf` into a `Rc<Path>`
-    ///
-    /// This conversion happens in place
-    ///
-    /// This conversion does not allocate memory
+    /// Converts a Path into a Rc by copying the Path data into a new Rc buffer.
     #[inline]
     fn from(s: PathBuf) -> Rc<Path> {
         let rc: Rc<OsStr> = Rc::from(s.into_os_string());
@@ -1594,6 +1582,7 @@ impl From<PathBuf> for Rc<Path> {
 
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl<'a> From<&'a Path> for Rc<Path> {
+    /// Converts a Path into a Rc by copying the Path data into a new Rc buffer.
     #[inline]
     fn from(s: &Path) -> Rc<Path> {
         let rc: Rc<OsStr> = Rc::from(s.as_os_str());

From 7933628de58851281544fe2a7b4e0d0673652e47 Mon Sep 17 00:00:00 2001
From: Bastian Gruber <gruberbastian@me.com>
Date: Wed, 21 Nov 2018 13:57:56 +0100
Subject: [PATCH 07/45] Remove trailing whitespace

---
 src/libstd/path.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libstd/path.rs b/src/libstd/path.rs
index 2d0a2501f7e99..dcd02ac59b6c8 100644
--- a/src/libstd/path.rs
+++ b/src/libstd/path.rs
@@ -1409,7 +1409,7 @@ impl From<Box<Path>> for PathBuf {
 impl From<PathBuf> for Box<Path> {
     /// Converts a `PathBuf` into a `Box<Path>`
     ///
-    /// This conversion currently should not allocate memory, 
+    /// This conversion currently should not allocate memory,
     // but this behavior is not guaranteed on all platforms or in all future versions.
     fn from(p: PathBuf) -> Box<Path> {
         p.into_boxed_path()

From c209ed84359804d200454f117946d41e5ac84159 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date: Thu, 1 Nov 2018 02:20:49 +0100
Subject: [PATCH 08/45] Improve no result found sentence in doc search

---
 src/librustdoc/html/static/main.js          | 11 ++++++++++-
 src/librustdoc/html/static/rustdoc.css      | 13 ++++++++++---
 src/librustdoc/html/static/themes/dark.css  |  2 +-
 src/librustdoc/html/static/themes/light.css |  2 +-
 4 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index 3174c1be3adc8..27b1dfc9ce39a 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -1340,7 +1340,16 @@
                 output = '<div class="search-failed"' + extraStyle + '>No results :(<br/>' +
                     'Try on <a href="https://duckduckgo.com/?q=' +
                     encodeURIComponent('rust ' + query.query) +
-                    '">DuckDuckGo</a>?</div>';
+                    '">DuckDuckGo</a>?<br/><br/>' +
+                    'Or try looking in one of these:<ul><li>The <a ' +
+                    'href="https://doc.rust-lang.org/reference/index.html">Rust Reference</a> for' +
+                    ' technical details about the language.</li><li><a ' +
+                    'href="https://doc.rust-lang.org/rust-by-example/index.html">Rust By Example' +
+                    '</a> for expository code examples.</a></li><li>The <a ' +
+                    'href="https://doc.rust-lang.org/book/index.html">Rust Book</a> for ' +
+                    'introductions to language features and the language itself.</li><li><a ' +
+                    'href="https://docs.rs">Docs.rs</a> for documentation of crates released on ' +
+                    '<a href="https://crates.io/">crates.io</a>.</li></ul></div>';
             }
             return [output, length];
         }
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index 8bcb828a5ade1..aa43a0bb58ad9 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -658,9 +658,9 @@ a {
 	padding-right: 10px;
 }
 .content .search-results td:first-child a:after {
-    clear: both;
-    content: "";
-    display: block;
+	clear: both;
+	content: "";
+	display: block;
 }
 .content .search-results td:first-child a span {
 	float: left;
@@ -1116,6 +1116,13 @@ pre.rust {
 	margin-top: 20px;
 }
 
+.search-failed > ul {
+	text-align: left;
+	max-width: 570px;
+	margin-left: auto;
+	margin-right: auto;
+}
+
 #titles {
 	height: 35px;
 }
diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css
index 4a8950b236c62..9c90c94858116 100644
--- a/src/librustdoc/html/static/themes/dark.css
+++ b/src/librustdoc/html/static/themes/dark.css
@@ -285,7 +285,7 @@ pre.ignore:hover, .information:hover + pre.ignore {
 	color: rgba(255,142,0,1);
 }
 
-.search-failed > a {
+.search-failed a {
 	color: #0089ff;
 }
 
diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css
index b3b0b6b2ea9e8..e839fc3f2783f 100644
--- a/src/librustdoc/html/static/themes/light.css
+++ b/src/librustdoc/html/static/themes/light.css
@@ -279,7 +279,7 @@ pre.ignore:hover, .information:hover + pre.ignore {
 	color: rgba(255,142,0,1);
 }
 
-.search-failed > a {
+.search-failed a {
 	color: #0089ff;
 }
 

From 47b5e23e6b72183b993584dc41c51652eb6adb3a Mon Sep 17 00:00:00 2001
From: Dale Wijnand <dale.wijnand@gmail.com>
Date: Mon, 26 Nov 2018 18:36:03 +0000
Subject: [PATCH 09/45] Introduce ptr::hash for references

---
 src/libcore/ptr.rs | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index e9cf11424cae1..6b4ee66bb02cf 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -2509,6 +2509,29 @@ pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool {
     a == b
 }
 
+/// Hash the raw pointer address behind a reference, rather than the value
+/// it points to.
+///
+/// # Examples
+///
+/// ```
+/// use std::collections::hash_map::DefaultHasher;
+/// use std::hash::Hasher;
+/// use std::ptr;
+///
+/// let five = 5;
+/// let five_ref = &five;
+///
+/// let mut hasher = DefaultHasher::new();
+/// ptr::hash(five_ref, hasher);
+/// println!("Hash is {:x}!", hasher.finish());
+/// ```
+#[stable(feature = "rust1", since = "1.0.0")] // TODO: replace with ???
+pub fn hash<T, S: hash::Hasher>(a: &T, into: &mut S) {
+    use hash::Hash;
+    NonNull::from(a).hash(into)
+}
+
 // Impls for function pointers
 macro_rules! fnptr_impls_safety_abi {
     ($FnTy: ty, $($Arg: ident),*) => {

From 86d20f9342c8b6cfd24d199eacb26ed11a95da12 Mon Sep 17 00:00:00 2001
From: Dale Wijnand <344610+dwijnand@users.noreply.github.com>
Date: Mon, 26 Nov 2018 19:23:20 +0000
Subject: [PATCH 10/45] FIXME is the new TODO

---
 src/libcore/ptr.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index 6b4ee66bb02cf..7a57c365b2301 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -2526,7 +2526,7 @@ pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool {
 /// ptr::hash(five_ref, hasher);
 /// println!("Hash is {:x}!", hasher.finish());
 /// ```
-#[stable(feature = "rust1", since = "1.0.0")] // TODO: replace with ???
+#[stable(feature = "rust1", since = "1.0.0")] // FIXME: replace with ???
 pub fn hash<T, S: hash::Hasher>(a: &T, into: &mut S) {
     use hash::Hash;
     NonNull::from(a).hash(into)

From 5558c07c6e24b6677e3a60a1314d705c8c23ab47 Mon Sep 17 00:00:00 2001
From: Dale Wijnand <344610+dwijnand@users.noreply.github.com>
Date: Mon, 26 Nov 2018 21:31:12 +0000
Subject: [PATCH 11/45] Fix ptr::hex doc example

---
 src/libcore/ptr.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index 7a57c365b2301..c0e8e58114414 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -2523,7 +2523,7 @@ pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool {
 /// let five_ref = &five;
 ///
 /// let mut hasher = DefaultHasher::new();
-/// ptr::hash(five_ref, hasher);
+/// ptr::hash(five_ref, &mut hasher);
 /// println!("Hash is {:x}!", hasher.finish());
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")] // FIXME: replace with ???

From 7b429b0440eb7e8888ea600ca2103cb13999b3a2 Mon Sep 17 00:00:00 2001
From: Dale Wijnand <dale.wijnand@gmail.com>
Date: Tue, 27 Nov 2018 16:25:38 +0000
Subject: [PATCH 12/45] Fix stability attribute for ptr::hash

---
 src/libcore/ptr.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index c0e8e58114414..13aae988d6c10 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -2526,7 +2526,7 @@ pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool {
 /// ptr::hash(five_ref, &mut hasher);
 /// println!("Hash is {:x}!", hasher.finish());
 /// ```
-#[stable(feature = "rust1", since = "1.0.0")] // FIXME: replace with ???
+#[unstable(feature = "ptr_hash", reason = "newly added", issue = "56285")]
 pub fn hash<T, S: hash::Hasher>(a: &T, into: &mut S) {
     use hash::Hash;
     NonNull::from(a).hash(into)

From 81251491ddecb5c55b6d22b04abf33ef65d3a74b Mon Sep 17 00:00:00 2001
From: Dale Wijnand <dale.wijnand@gmail.com>
Date: Tue, 27 Nov 2018 16:33:01 +0000
Subject: [PATCH 13/45] Pick a better variable name for ptr::hash

---
 src/libcore/ptr.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index 13aae988d6c10..ff679d92e6096 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -2527,9 +2527,9 @@ pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool {
 /// println!("Hash is {:x}!", hasher.finish());
 /// ```
 #[unstable(feature = "ptr_hash", reason = "newly added", issue = "56285")]
-pub fn hash<T, S: hash::Hasher>(a: &T, into: &mut S) {
+pub fn hash<T, S: hash::Hasher>(hashee: &T, into: &mut S) {
     use hash::Hash;
-    NonNull::from(a).hash(into)
+    NonNull::from(hashee).hash(into)
 }
 
 // Impls for function pointers

From afb4fbd951bc9780b5a7812f9a72aa9e2f085814 Mon Sep 17 00:00:00 2001
From: Dale Wijnand <dale.wijnand@gmail.com>
Date: Tue, 27 Nov 2018 16:46:24 +0000
Subject: [PATCH 14/45] Add an assert_eq in ptr::hash's doc example

---
 src/libcore/ptr.rs | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index ff679d92e6096..7b93795728b92 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -2524,7 +2524,13 @@ pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool {
 ///
 /// let mut hasher = DefaultHasher::new();
 /// ptr::hash(five_ref, &mut hasher);
-/// println!("Hash is {:x}!", hasher.finish());
+/// let actual = hasher.finish();
+///
+/// let mut hasher = DefaultHasher::new();
+/// (five_ref as *const T).hash(&mut hasher);
+/// let expected = hasher.finish();
+///
+/// assert_eq!(actual, expected);
 /// ```
 #[unstable(feature = "ptr_hash", reason = "newly added", issue = "56285")]
 pub fn hash<T, S: hash::Hasher>(hashee: &T, into: &mut S) {

From 4a7ffe2646b5d152297ab8008cc64693b4fd3d0a Mon Sep 17 00:00:00 2001
From: Dale Wijnand <dale.wijnand@gmail.com>
Date: Tue, 27 Nov 2018 16:46:59 +0000
Subject: [PATCH 15/45] Fix issue number

---
 src/libcore/ptr.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index 7b93795728b92..7c8b195db8f1c 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -2532,7 +2532,7 @@ pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool {
 ///
 /// assert_eq!(actual, expected);
 /// ```
-#[unstable(feature = "ptr_hash", reason = "newly added", issue = "56285")]
+#[unstable(feature = "ptr_hash", reason = "newly added", issue = "56286")]
 pub fn hash<T, S: hash::Hasher>(hashee: &T, into: &mut S) {
     use hash::Hash;
     NonNull::from(hashee).hash(into)

From 9755410f73584909ffa2f3241a946d47139d1902 Mon Sep 17 00:00:00 2001
From: Dale Wijnand <dale.wijnand@gmail.com>
Date: Tue, 27 Nov 2018 20:09:18 +0000
Subject: [PATCH 16/45] Try to fix ptr::hash's doc example

---
 src/libcore/ptr.rs | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index 7c8b195db8f1c..3024031b3bb29 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -2516,18 +2516,19 @@ pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool {
 ///
 /// ```
 /// use std::collections::hash_map::DefaultHasher;
-/// use std::hash::Hasher;
+/// use std::hash::{Hash, Hasher};
 /// use std::ptr;
 ///
 /// let five = 5;
 /// let five_ref = &five;
 ///
 /// let mut hasher = DefaultHasher::new();
+/// #[feature(ptr_hash)]
 /// ptr::hash(five_ref, &mut hasher);
 /// let actual = hasher.finish();
 ///
 /// let mut hasher = DefaultHasher::new();
-/// (five_ref as *const T).hash(&mut hasher);
+/// (five_ref as *const i32).hash(&mut hasher);
 /// let expected = hasher.finish();
 ///
 /// assert_eq!(actual, expected);

From 097b5db5f67c28719d0065c6a74a2e56ae52d2d3 Mon Sep 17 00:00:00 2001
From: Dale Wijnand <dale.wijnand@gmail.com>
Date: Tue, 27 Nov 2018 21:18:20 +0000
Subject: [PATCH 17/45] Move feature enable in ptr::hash doc example

---
 src/libcore/ptr.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index 3024031b3bb29..0213b310efaa3 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -2515,6 +2515,7 @@ pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool {
 /// # Examples
 ///
 /// ```
+/// #![feature(ptr_hash)]
 /// use std::collections::hash_map::DefaultHasher;
 /// use std::hash::{Hash, Hasher};
 /// use std::ptr;
@@ -2523,7 +2524,6 @@ pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool {
 /// let five_ref = &five;
 ///
 /// let mut hasher = DefaultHasher::new();
-/// #[feature(ptr_hash)]
 /// ptr::hash(five_ref, &mut hasher);
 /// let actual = hasher.finish();
 ///

From dd717deccb3a4698beac8edb0a75e2efb6f08ebb Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date: Mon, 1 Oct 2018 00:47:54 +0200
Subject: [PATCH 18/45] Add crate filtering

---
 src/librustdoc/html/layout.rs               | 15 ++--
 src/librustdoc/html/render.rs               |  2 +-
 src/librustdoc/html/static/main.js          | 99 +++++++++++++++++----
 src/librustdoc/html/static/rustdoc.css      | 24 ++++-
 src/librustdoc/html/static/themes/dark.css  |  8 +-
 src/librustdoc/html/static/themes/light.css |  9 +-
 6 files changed, 131 insertions(+), 26 deletions(-)

diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs
index 6868c7707adc8..d585b737517b3 100644
--- a/src/librustdoc/html/layout.rs
+++ b/src/librustdoc/html/layout.rs
@@ -81,11 +81,16 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
     <nav class=\"sub\">\
         <form class=\"search-form js-only\">\
             <div class=\"search-container\">\
-                <input class=\"search-input\" name=\"search\" \
-                       autocomplete=\"off\" \
-                       spellcheck=\"false\" \
-                       placeholder=\"Click or press ‘S’ to search, ‘?’ for more options…\" \
-                       type=\"search\">\
+                <div>\
+                    <select id=\"crate-search\">\
+                        <option value=\"All crates\">All crates</option>\
+                    </select>\
+                    <input class=\"search-input\" name=\"search\" \
+                           autocomplete=\"off\" \
+                           spellcheck=\"false\" \
+                           placeholder=\"Click or press ‘S’ to search, ‘?’ for more options…\" \
+                           type=\"search\">\
+                </div>\
                 <a id=\"settings-menu\" href=\"{root_path}settings.html\">\
                     <img src=\"{root_path}wheel{suffix}.svg\" width=\"18\" alt=\"Change settings\">\
                 </a>\
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index f560350d5105d..48da90de02a8a 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -983,7 +983,7 @@ themePicker.onblur = handleThemeButtonsBlur;
                                        &[(minifier::js::Keyword::Null, "N")]),
                  &dst);
     }
-    try_err!(writeln!(&mut w, "initSearch(searchIndex);"), &dst);
+    try_err!(writeln!(&mut w, "initSearch(searchIndex);addSearchOptions(searchIndex);"), &dst);
 
     if options.enable_index_page {
         if let Some(index_page) = options.index_page.clone() {
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index 4425712eed7a1..66e10b24440be 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -254,12 +254,14 @@
     //
     // So I guess you could say things are getting pretty interoperable.
     function getVirtualKey(ev) {
-        if ("key" in ev && typeof ev.key != "undefined")
+        if ("key" in ev && typeof ev.key != "undefined") {
             return ev.key;
+        }
 
         var c = ev.charCode || ev.keyCode;
-        if (c == 27)
+        if (c == 27) {
             return "Escape";
+        }
         return String.fromCharCode(c);
     }
 
@@ -467,12 +469,13 @@
 
         /**
          * Executes the query and builds an index of results
-         * @param  {[Object]} query     [The user query]
-         * @param  {[type]} searchWords [The list of search words to query
-         *                               against]
-         * @return {[type]}             [A search index of results]
+         * @param  {[Object]} query      [The user query]
+         * @param  {[type]} searchWords  [The list of search words to query
+         *                                against]
+         * @param  {[type]} filterCrates [Crate to search in if defined]
+         * @return {[type]}              [A search index of results]
          */
-        function execQuery(query, searchWords) {
+        function execQuery(query, searchWords, filterCrates) {
             function itemTypeFromName(typename) {
                 for (var i = 0; i < itemTypes.length; ++i) {
                     if (itemTypes[i] === typename) {
@@ -848,6 +851,9 @@
             {
                 val = extractGenerics(val.substr(1, val.length - 2));
                 for (var i = 0; i < nSearchWords; ++i) {
+                    if (filterCrates !== undefined && searchIndex[i].crate !== filterCrates) {
+                        continue;
+                    }
                     var in_args = findArg(searchIndex[i], val, true);
                     var returned = checkReturned(searchIndex[i], val, true);
                     var ty = searchIndex[i];
@@ -902,6 +908,9 @@
                 var output = extractGenerics(parts[1]);
 
                 for (var i = 0; i < nSearchWords; ++i) {
+                    if (filterCrates !== undefined && searchIndex[i].crate !== filterCrates) {
+                        continue;
+                    }
                     var type = searchIndex[i].type;
                     var ty = searchIndex[i];
                     if (!type) {
@@ -973,11 +982,11 @@
                 var contains = paths.slice(0, paths.length > 1 ? paths.length - 1 : 1);
 
                 for (j = 0; j < nSearchWords; ++j) {
-                    var lev_distance;
                     var ty = searchIndex[j];
-                    if (!ty) {
+                    if (!ty || (filterCrates !== undefined && ty.crate !== filterCrates)) {
                         continue;
                     }
+                    var lev_distance;
                     var lev_add = 0;
                     if (paths.length > 1) {
                         var lev = checkPath(contains, paths[paths.length - 1], ty);
@@ -1353,7 +1362,7 @@
             return '<div>' + text + ' <div class="count">(' + nbElems + ')</div></div>';
         }
 
-        function showResults(results) {
+        function showResults(results, filterCrates) {
             if (results['others'].length === 1 &&
                 getCurrentValue('rustdoc-go-to-only-result') === "true") {
                 var elem = document.createElement('a');
@@ -1371,8 +1380,13 @@
             var ret_in_args = addTab(results['in_args'], query, false);
             var ret_returned = addTab(results['returned'], query, false);
 
+            var filter = "";
+            if (filterCrates !== undefined) {
+                filter = " (in <b>" + filterCrates + "</b> crate)";
+            }
+
             var output = '<h1>Results for ' + escape(query.query) +
-                (query.type ? ' (type: ' + escape(query.type) + ')' : '') + '</h1>' +
+                (query.type ? ' (type: ' + escape(query.type) + ')' : '') + filter + '</h1>' +
                 '<div id="titles">' +
                 makeTabHeader(0, "In Names", ret_others[1]) +
                 makeTabHeader(1, "In Parameters", ret_in_args[1]) +
@@ -1401,7 +1415,7 @@
             printTab(currentTab);
         }
 
-        function execSearch(query, searchWords) {
+        function execSearch(query, searchWords, filterCrates) {
             var queries = query.raw.split(",");
             var results = {
                 'in_args': [],
@@ -1412,7 +1426,7 @@
             for (var i = 0; i < queries.length; ++i) {
                 var query = queries[i].trim();
                 if (query.length !== 0) {
-                    var tmp = execQuery(getQuery(query), searchWords);
+                    var tmp = execQuery(getQuery(query), searchWords, filterCrates);
 
                     results['in_args'].push(tmp['in_args']);
                     results['returned'].push(tmp['returned']);
@@ -1474,7 +1488,16 @@
             }
         }
 
-        function search(e) {
+        function getFilterCrates() {
+            var elem = document.getElementById("crate-search");
+
+            if (elem && elem.value !== "All crates" && rawSearchIndex.hasOwnProperty(elem.value)) {
+                return elem.value;
+            }
+            return undefined;
+        }
+
+        function search(e, forced) {
             var params = getQueryStringParams();
             var query = getQuery(search_input.value.trim());
 
@@ -1482,7 +1505,10 @@
                 e.preventDefault();
             }
 
-            if (query.query.length === 0 || query.id === currentResults) {
+            if (query.query.length === 0) {
+                return;
+            }
+            if (forced !== true && query.id === currentResults) {
                 if (query.query.length > 0) {
                     putBackSearch(search_input);
                 }
@@ -1502,7 +1528,8 @@
                 }
             }
 
-            showResults(execSearch(query, index));
+            var filterCrates = getFilterCrates();
+            showResults(execSearch(query, index, filterCrates), filterCrates);
         }
 
         function buildIndex(rawSearchIndex) {
@@ -1602,6 +1629,13 @@
             };
             search_input.onpaste = search_input.onchange;
 
+            var selectCrate = document.getElementById('crate-search');
+            if (selectCrate) {
+                selectCrate.onchange = function() {
+                    search(undefined, true);
+                };
+            }
+
             // Push and pop states are used to add search results to the browser
             // history.
             if (browserSupportsHistoryApi()) {
@@ -2350,6 +2384,39 @@
     if (window.location.hash && window.location.hash.length > 0) {
         expandSection(window.location.hash.replace(/^#/, ''));
     }
+
+    function addSearchOptions(crates) {
+        var elem = document.getElementById('crate-search');
+
+        if (!elem) {
+            return;
+        }
+        var crates_text = [];
+        for (var crate in crates) {
+            if (crates.hasOwnProperty(crate)) {
+                crates_text.push(crate);
+            }
+        }
+        crates_text.sort(function(a, b) {
+            var lower_a = a.toLowerCase();
+            var lower_b = b.toLowerCase();
+
+            if (lower_a < lower_b) {
+                return -1;
+            } else if (lower_a > lower_b) {
+                return 1;
+            }
+            return 0;
+        });
+        for (var i = 0; i < crates_text.length; ++i) {
+            var option = document.createElement("option");
+            option.value = crates_text[i];
+            option.innerText = crates_text[i];
+            elem.appendChild(option);
+        }
+    }
+
+    window.addSearchOptions = addSearchOptions;
 }());
 
 // Sets the focus on the search bar at the top of the page
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index 1ae3b0b88c6dd..cbf55c12244d1 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -614,13 +614,32 @@ a {
 .search-container {
 	position: relative;
 }
+.search-container > div {
+	display: inline-flex;
+	width: calc(100% - 34px);
+}
+#crate-search {
+	margin-top: 5px;
+	padding: 6px;
+	padding-right: 12px;
+	border: 0;
+	border-right: 0;
+	border-radius: 4px 0 0 4px;
+	outline: none;
+	cursor: pointer;
+	border-right: 1px solid;
+	-moz-appearance: none;
+	-webkit-appearance: none;
+	/* Removes default arrow from firefox */
+	text-indent: 0.01px;
+	text-overflow: "";
+}
 .search-container > .top-button {
 	position: absolute;
 	right: 0;
 	top: 10px;
 }
 .search-input {
-	width: calc(100% - 34px);
 	/* Override Normalize.css: we have margins and do
 	 not want to overflow - the `moz` attribute is necessary
 	 until Firefox 29, too early to drop at this point */
@@ -628,13 +647,14 @@ a {
 	box-sizing: border-box !important;
 	outline: none;
 	border: none;
-	border-radius: 1px;
+	border-radius: 0 1px 1px 0;
 	margin-top: 5px;
 	padding: 10px 16px;
 	font-size: 17px;
 	transition: border-color 300ms ease;
 	transition: border-radius 300ms ease-in-out;
 	transition: box-shadow 300ms ease-in-out;
+	width: 100%;
 }
 
 .search-input:focus {
diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css
index 4a8950b236c62..8fdf39ccaa1a6 100644
--- a/src/librustdoc/html/static/themes/dark.css
+++ b/src/librustdoc/html/static/themes/dark.css
@@ -182,9 +182,15 @@ a.test-arrow {
 	color: #999;
 }
 
+#crate-search {
+	color: #111;
+	background-color: #f0f0f0;
+	border-color: #000;
+}
+
 .search-input {
 	color: #111;
-	box-shadow: 0 0 0 1px #000, 0 0 0 2px transparent;
+	box-shadow: 1px 0 0 1px #000, 0 0 0 2px transparent;
 	background-color: #f0f0f0;
 }
 
diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css
index b3b0b6b2ea9e8..425aa601e9b3e 100644
--- a/src/librustdoc/html/static/themes/light.css
+++ b/src/librustdoc/html/static/themes/light.css
@@ -182,9 +182,16 @@ a.test-arrow {
 	color: #999;
 }
 
+#crate-search {
+	color: #555;
+	background-color: white;
+	border-color: #e0e0e0;
+	box-shadow: 0px 0 0 1px #e0e0e0, 0 0 0 2px transparent;
+}
+
 .search-input {
 	color: #555;
-	box-shadow: 0 0 0 1px #e0e0e0, 0 0 0 2px transparent;
+	box-shadow: 1px 0 0 1px #e0e0e0, 0 0 0 2px transparent;
 	background-color: white;
 }
 

From 8062c7ae4b6201b3728baae37fb04215dcc5fcd4 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date: Mon, 1 Oct 2018 00:55:00 +0200
Subject: [PATCH 19/45] Add test for crate filtering

---
 src/test/rustdoc-js/filter-crate.js | 20 ++++++++++++++++++++
 src/tools/rustdoc-js/tester.js      |  1 +
 2 files changed, 21 insertions(+)
 create mode 100644 src/test/rustdoc-js/filter-crate.js

diff --git a/src/test/rustdoc-js/filter-crate.js b/src/test/rustdoc-js/filter-crate.js
new file mode 100644
index 0000000000000..69c959a6ef21c
--- /dev/null
+++ b/src/test/rustdoc-js/filter-crate.js
@@ -0,0 +1,20 @@
+// 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.
+
+// should-fail
+
+const QUERY = 'string';
+const FILTER_CRATE = 'core';
+
+const EXPECTED = {
+    'others': [
+        { 'path': 'std::collections', 'name': 'VecDeque' },
+    ],
+};
diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js
index c8ce4cf8bb5be..f7c30df9f3ebb 100644
--- a/src/tools/rustdoc-js/tester.js
+++ b/src/tools/rustdoc-js/tester.js
@@ -259,6 +259,7 @@ function main(argv) {
                                'exports.QUERY = QUERY;exports.EXPECTED = EXPECTED;');
         const expected = loadedFile.EXPECTED;
         const query = loadedFile.QUERY;
+        const filter_crate = loadedFile.FILTER_CRATE;
         const ignore_order = loadedFile.ignore_order;
         const exact_check = loadedFile.exact_check;
         const should_fail = loadedFile.should_fail;

From afe41078add129c821a16f5f7fb6e667c34c153d Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date: Thu, 29 Nov 2018 01:29:49 +0100
Subject: [PATCH 20/45] Add arrow to the crate select box

---
 src/librustdoc/html/layout.rs             | 3 +++
 src/librustdoc/html/render.rs             | 2 ++
 src/librustdoc/html/static/down-arrow.svg | 1 +
 src/librustdoc/html/static/rustdoc.css    | 6 +++++-
 src/librustdoc/html/static_files.rs       | 3 +++
 5 files changed, 14 insertions(+), 1 deletion(-)
 create mode 100644 src/librustdoc/html/static/down-arrow.svg

diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs
index d585b737517b3..3a2a6f4c6b9fd 100644
--- a/src/librustdoc/html/layout.rs
+++ b/src/librustdoc/html/layout.rs
@@ -57,6 +57,9 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
     {css_extension}\
     {favicon}\
     {in_header}\
+    <style type=\"text/css\">\
+    #crate-search{{background-image:url(\"{root_path}down-arrow{suffix}.svg\");}}\
+    </style>\
 </head>\
 <body class=\"rustdoc {css_class}\">\
     <!--[if lte IE 8]>\
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 48da90de02a8a..1b99641c3e773 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -793,6 +793,8 @@ fn write_shared(
           static_files::BRUSH_SVG)?;
     write(cx.dst.join(&format!("wheel{}.svg", cx.shared.resource_suffix)),
           static_files::WHEEL_SVG)?;
+    write(cx.dst.join(&format!("down-arrow{}.svg", cx.shared.resource_suffix)),
+          static_files::DOWN_ARROW_SVG)?;
     write_minify(cx.dst.join(&format!("light{}.css", cx.shared.resource_suffix)),
                  static_files::themes::LIGHT,
                  options.enable_minification)?;
diff --git a/src/librustdoc/html/static/down-arrow.svg b/src/librustdoc/html/static/down-arrow.svg
new file mode 100644
index 0000000000000..a2d9a37dde091
--- /dev/null
+++ b/src/librustdoc/html/static/down-arrow.svg
@@ -0,0 +1 @@
+<?xml version="1.0" ?><!DOCTYPE svg  PUBLIC '-//W3C//DTD SVG 1.1//EN'  'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'><svg height="128px" id="Layer_1" style="enable-background:new 0 0 128 128;" version="1.1" viewBox="0 0 128 128" width="128px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g><line style="fill:none;stroke:#2F3435;stroke-width:12;stroke-linecap:square;stroke-miterlimit:10;" x1="111" x2="64" y1="40.5" y2="87.499"/><line style="fill:none;stroke:#2F3435;stroke-width:12;stroke-linecap:square;stroke-miterlimit:10;" x1="64" x2="17" y1="87.499" y2="40.5"/></g></svg>
\ No newline at end of file
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index cbf55c12244d1..ff1ba9f541b02 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -621,7 +621,7 @@ a {
 #crate-search {
 	margin-top: 5px;
 	padding: 6px;
-	padding-right: 12px;
+	padding-right: 19px;
 	border: 0;
 	border-right: 0;
 	border-radius: 4px 0 0 4px;
@@ -633,6 +633,10 @@ a {
 	/* Removes default arrow from firefox */
 	text-indent: 0.01px;
 	text-overflow: "";
+	background-repeat: no-repeat;
+	background-color: transparent;
+	background-size: 16%;
+	background-position: calc(100% - 1px) 56%;
 }
 .search-container > .top-button {
 	position: absolute;
diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs
index 3baa082bd0e69..93f95d8892e48 100644
--- a/src/librustdoc/html/static_files.rs
+++ b/src/librustdoc/html/static_files.rs
@@ -45,6 +45,9 @@ pub static BRUSH_SVG: &'static [u8] = include_bytes!("static/brush.svg");
 /// The file contents of `wheel.svg`, the icon used for the settings button.
 pub static WHEEL_SVG: &'static [u8] = include_bytes!("static/wheel.svg");
 
+/// The file contents of `down-arrow.svg`, the icon used for the crate choice combobox.
+pub static DOWN_ARROW_SVG: &'static [u8] = include_bytes!("static/down-arrow.svg");
+
 /// The contents of `COPYRIGHT.txt`, the license listing for files distributed with documentation
 /// output.
 pub static COPYRIGHT: &'static [u8] = include_bytes!("static/COPYRIGHT.txt");

From 1560a75f6a7dfd51e4d7f6603e3959388d4bcb03 Mon Sep 17 00:00:00 2001
From: Daan de Graaf <daandegraaf9@gmail.com>
Date: Fri, 30 Nov 2018 14:55:51 +0100
Subject: [PATCH 21/45] Refer to the second borrow as the "second borrow".

---
 src/librustc_borrowck/borrowck/check_loans.rs         |  2 +-
 src/librustc_mir/borrow_check/error_reporting.rs      | 11 ++++++++++-
 .../borrow_check/nll/explain_borrow/mod.rs            |  6 ++++++
 src/librustc_mir/util/borrowck_errors.rs              |  6 +++++-
 src/test/ui/E0501.ast.nll.stderr                      |  4 ++--
 src/test/ui/E0501.mir.stderr                          |  4 ++--
 .../borrowck/borrowck-insert-during-each.nll.stderr   |  2 +-
 .../generator/yield-while-ref-reborrowed.nll.stderr   |  2 +-
 src/test/ui/nll/closure-borrow-spans.stderr           |  4 ++--
 9 files changed, 30 insertions(+), 11 deletions(-)

diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs
index a802729e3fbdb..e47e95afb1643 100644
--- a/src/librustc_borrowck/borrowck/check_loans.rs
+++ b/src/librustc_borrowck/borrowck/check_loans.rs
@@ -615,7 +615,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
                     let new_loan_str = &new_loan.kind.to_user_str();
                     self.bccx.cannot_reborrow_already_uniquely_borrowed(
                         new_loan.span, "closure", &nl, &new_loan_msg, new_loan_str,
-                        old_loan.span, &old_loan_msg, previous_end_span, Origin::Ast)
+                        old_loan.span, &old_loan_msg, previous_end_span, "", Origin::Ast)
                 }
                 (..) =>
                     self.bccx.cannot_reborrow_already_borrowed(
diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs
index 4ccd26bee8b88..ba26ed36c20f4 100644
--- a/src/librustc_mir/borrow_check/error_reporting.rs
+++ b/src/librustc_mir/borrow_check/error_reporting.rs
@@ -344,6 +344,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
 
         let first_borrow_desc;
 
+        let explanation = self.explain_why_borrow_contains_point(context, issued_borrow, None);
+        let second_borrow_desc = if explanation.is_explained() {
+            "second "
+        } else {
+            ""
+        };
+
         // FIXME: supply non-"" `opt_via` when appropriate
         let mut err = match (
             gen_borrow_kind,
@@ -454,6 +461,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                     issued_span,
                     "",
                     None,
+                    second_borrow_desc,
                     Origin::Mir,
                 )
             }
@@ -469,6 +477,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                     issued_span,
                     "",
                     None,
+                    second_borrow_desc,
                     Origin::Mir,
                 )
             }
@@ -513,7 +522,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
             );
         }
 
-        self.explain_why_borrow_contains_point(context, issued_borrow, None)
+        explanation
             .add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, first_borrow_desc);
 
         err.buffer(&mut self.errors_buffer);
diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
index bb9a29b055b7f..477b78926084e 100644
--- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
@@ -52,6 +52,12 @@ pub(in borrow_check) enum LaterUseKind {
 }
 
 impl BorrowExplanation {
+    pub(in borrow_check) fn is_explained(&self) -> bool {
+        match self {
+            BorrowExplanation::Unexplained => false,
+            _ => true,
+        }
+    }
     pub(in borrow_check) fn add_explanation_to_diagnostic<'cx, 'gcx, 'tcx>(
         &self,
         tcx: TyCtxt<'cx, 'gcx, 'tcx>,
diff --git a/src/librustc_mir/util/borrowck_errors.rs b/src/librustc_mir/util/borrowck_errors.rs
index ae0483e3c140c..8566f845f23e3 100644
--- a/src/librustc_mir/util/borrowck_errors.rs
+++ b/src/librustc_mir/util/borrowck_errors.rs
@@ -261,6 +261,7 @@ pub trait BorrowckErrors<'cx>: Sized + Copy {
         old_loan_span: Span,
         old_opt_via: &str,
         previous_end_span: Option<Span>,
+        second_borrow_desc: &str,
         o: Origin,
     ) -> DiagnosticBuilder<'cx> {
         let mut err = struct_span_err!(
@@ -274,7 +275,10 @@ pub trait BorrowckErrors<'cx>: Sized + Copy {
             kind_new,
             OGN = o
         );
-        err.span_label(new_loan_span, format!("borrow occurs here{}", opt_via));
+        err.span_label(
+            new_loan_span,
+            format!("{}borrow occurs here{}", second_borrow_desc, opt_via),
+        );
         err.span_label(
             old_loan_span,
             format!("{} construction occurs here{}", container_name, old_opt_via),
diff --git a/src/test/ui/E0501.ast.nll.stderr b/src/test/ui/E0501.ast.nll.stderr
index 72fda9079d636..8a3fce3a554eb 100644
--- a/src/test/ui/E0501.ast.nll.stderr
+++ b/src/test/ui/E0501.ast.nll.stderr
@@ -7,7 +7,7 @@ LL |         inside_closure(a)
    |                        - first borrow occurs due to use of `a` in closure
 LL |     };
 LL |     outside_closure_1(a); //[ast]~ ERROR cannot borrow `*a` as mutable because previous closure requires unique access
-   |                       ^ borrow occurs here
+   |                       ^ second borrow occurs here
 ...
 LL |     drop(bar);
    |          --- first borrow later used here
@@ -21,7 +21,7 @@ LL |         inside_closure(a)
    |                        - first borrow occurs due to use of `a` in closure
 ...
 LL |     outside_closure_2(a); //[ast]~ ERROR cannot borrow `*a` as immutable because previous closure requires unique access
-   |                       ^ borrow occurs here
+   |                       ^ second borrow occurs here
 ...
 LL |     drop(bar);
    |          --- first borrow later used here
diff --git a/src/test/ui/E0501.mir.stderr b/src/test/ui/E0501.mir.stderr
index 72fda9079d636..8a3fce3a554eb 100644
--- a/src/test/ui/E0501.mir.stderr
+++ b/src/test/ui/E0501.mir.stderr
@@ -7,7 +7,7 @@ LL |         inside_closure(a)
    |                        - first borrow occurs due to use of `a` in closure
 LL |     };
 LL |     outside_closure_1(a); //[ast]~ ERROR cannot borrow `*a` as mutable because previous closure requires unique access
-   |                       ^ borrow occurs here
+   |                       ^ second borrow occurs here
 ...
 LL |     drop(bar);
    |          --- first borrow later used here
@@ -21,7 +21,7 @@ LL |         inside_closure(a)
    |                        - first borrow occurs due to use of `a` in closure
 ...
 LL |     outside_closure_2(a); //[ast]~ ERROR cannot borrow `*a` as immutable because previous closure requires unique access
-   |                       ^ borrow occurs here
+   |                       ^ second borrow occurs here
 ...
 LL |     drop(bar);
    |          --- first borrow later used here
diff --git a/src/test/ui/borrowck/borrowck-insert-during-each.nll.stderr b/src/test/ui/borrowck/borrowck-insert-during-each.nll.stderr
index 123d475f1c09f..84fc69465cb4a 100644
--- a/src/test/ui/borrowck/borrowck-insert-during-each.nll.stderr
+++ b/src/test/ui/borrowck/borrowck-insert-during-each.nll.stderr
@@ -10,7 +10,7 @@ LL | |         |a| { //~ ERROR closure requires unique access to `f`
 LL | |             f.n.insert(*a);
    | |             - first borrow occurs due to use of `f` in closure
 LL | |         })
-   | |__________^ borrow occurs here
+   | |__________^ second borrow occurs here
 
 error[E0500]: closure requires unique access to `f` but it is already borrowed
   --> $DIR/borrowck-insert-during-each.rs:27:9
diff --git a/src/test/ui/generator/yield-while-ref-reborrowed.nll.stderr b/src/test/ui/generator/yield-while-ref-reborrowed.nll.stderr
index 8dabb3c2505b6..60163d78e78f9 100644
--- a/src/test/ui/generator/yield-while-ref-reborrowed.nll.stderr
+++ b/src/test/ui/generator/yield-while-ref-reborrowed.nll.stderr
@@ -7,7 +7,7 @@ LL |         let a = &mut *x;
    |                       - first borrow occurs due to use of `x` in generator
 ...
 LL |     println!("{}", x); //~ ERROR
-   |                    ^ borrow occurs here
+   |                    ^ second borrow occurs here
 LL |     b.resume();
    |     - first borrow later used here
 
diff --git a/src/test/ui/nll/closure-borrow-spans.stderr b/src/test/ui/nll/closure-borrow-spans.stderr
index 3e423dadd192c..98a261657b1e7 100644
--- a/src/test/ui/nll/closure-borrow-spans.stderr
+++ b/src/test/ui/nll/closure-borrow-spans.stderr
@@ -126,7 +126,7 @@ LL |     let f = || *x = 0;
    |             |
    |             closure construction occurs here
 LL |     let y = &x; //~ ERROR
-   |             ^^ borrow occurs here
+   |             ^^ second borrow occurs here
 LL |     f.use_ref();
    |     - first borrow later used here
 
@@ -138,7 +138,7 @@ LL |     let f = || *x = 0;
    |             |
    |             closure construction occurs here
 LL |     let y = &mut x; //~ ERROR
-   |             ^^^^^^ borrow occurs here
+   |             ^^^^^^ second borrow occurs here
 LL |     f.use_ref();
    |     - first borrow later used here
 

From d92287a4e94a5ca729867ae8af146bfaed197542 Mon Sep 17 00:00:00 2001
From: Matthew Jasper <mjjasper1@gmail.com>
Date: Fri, 30 Nov 2018 21:22:04 +0000
Subject: [PATCH 22/45] Fix some rustc doc links

---
 .../transform/cleanup_post_borrowck.rs        | 26 ++++++++++++-------
 1 file changed, 17 insertions(+), 9 deletions(-)

diff --git a/src/librustc_mir/transform/cleanup_post_borrowck.rs b/src/librustc_mir/transform/cleanup_post_borrowck.rs
index c0edd3926d32d..6d7fc404edbb1 100644
--- a/src/librustc_mir/transform/cleanup_post_borrowck.rs
+++ b/src/librustc_mir/transform/cleanup_post_borrowck.rs
@@ -10,17 +10,25 @@
 
 //! This module provides two passes:
 //!
-//!   - [CleanAscribeUserType], that replaces all
-//!     [StatementKind::AscribeUserType] statements with [StatementKind::Nop].
-//!   - [CleanFakeReadsAndBorrows], that replaces all [FakeRead] statements and
-//!     borrows that are read by [FakeReadCause::ForMatchGuard] fake reads with
-//!     [StatementKind::Nop].
+//!   - [`CleanAscribeUserType`], that replaces all [`AscribeUserType`]
+//!     statements with [`Nop`].
+//!   - [`CleanFakeReadsAndBorrows`], that replaces all [`FakeRead`] statements
+//!     and borrows that are read by [`ForMatchGuard`] fake reads with [`Nop`].
 //!
-//! The [CleanFakeReadsAndBorrows] "pass" is actually implemented as two
+//! The `CleanFakeReadsAndBorrows` "pass" is actually implemented as two
 //! traversals (aka visits) of the input MIR. The first traversal,
-//! [DeleteAndRecordFakeReads], deletes the fake reads and finds the temporaries
-//! read by [ForMatchGuard] reads, and [DeleteFakeBorrows] deletes the
-//! initialization of those temporaries.
+//! [`DeleteAndRecordFakeReads`], deletes the fake reads and finds the
+//! temporaries read by [`ForMatchGuard`] reads, and [`DeleteFakeBorrows`]
+//! deletes the initialization of those temporaries.
+//!
+//! [`CleanAscribeUserType`]: cleanup_post_borrowck::CleanAscribeUserType
+//! [`CleanFakeReadsAndBorrows`]: cleanup_post_borrowck::CleanFakeReadsAndBorrows
+//! [`DeleteAndRecordFakeReads`]: cleanup_post_borrowck::DeleteAndRecordFakeReads
+//! [`DeleteFakeBorrows`]: cleanup_post_borrowck::DeleteFakeBorrows
+//! [`AscribeUserType`]: rustc::mir::StatementKind::AscribeUserType
+//! [`Nop`]: rustc::mir::StatementKind::Nop
+//! [`FakeRead`]: rustc::mir::StatementKind::FakeRead
+//! [`ForMatchGuard`]: rustc::mir::FakeReadCause::ForMatchGuard
 
 use rustc_data_structures::fx::FxHashSet;
 

From 4f5b8eace152601d20ac7d4aa3b9c9de0f45dd62 Mon Sep 17 00:00:00 2001
From: Matthew Jasper <mjjasper1@gmail.com>
Date: Fri, 30 Nov 2018 21:48:31 +0000
Subject: [PATCH 23/45] Remove the `region_map` field from `BorrowSet`

---
 src/librustc_mir/borrow_check/borrow_set.rs | 10 +---------
 src/librustc_mir/dataflow/impls/borrows.rs  |  9 +--------
 2 files changed, 2 insertions(+), 17 deletions(-)

diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs
index fd7dc7fc4bd3a..a6af79ffbe922 100644
--- a/src/librustc_mir/borrow_check/borrow_set.rs
+++ b/src/librustc_mir/borrow_check/borrow_set.rs
@@ -16,7 +16,7 @@ use rustc::mir::traversal;
 use rustc::mir::visit::{
     PlaceContext, Visitor, NonUseContext, MutatingUseContext, NonMutatingUseContext
 };
-use rustc::mir::{self, Location, Mir, Place, Local};
+use rustc::mir::{self, Location, Mir, Local};
 use rustc::ty::{RegionVid, TyCtxt};
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
 use rustc_data_structures::indexed_vec::IndexVec;
@@ -41,10 +41,6 @@ crate struct BorrowSet<'tcx> {
     /// only need to store one borrow index
     crate activation_map: FxHashMap<Location, Vec<BorrowIndex>>,
 
-    /// Every borrow has a region; this maps each such regions back to
-    /// its borrow-indexes.
-    crate region_map: FxHashMap<RegionVid, FxHashSet<BorrowIndex>>,
-
     /// Map from local to all the borrows on that local
     crate local_map: FxHashMap<mir::Local, FxHashSet<BorrowIndex>>,
 
@@ -149,7 +145,6 @@ impl<'tcx> BorrowSet<'tcx> {
             idx_vec: IndexVec::new(),
             location_map: Default::default(),
             activation_map: Default::default(),
-            region_map: Default::default(),
             local_map: Default::default(),
             pending_activations: Default::default(),
             locals_state_at_exit:
@@ -164,7 +159,6 @@ impl<'tcx> BorrowSet<'tcx> {
             borrows: visitor.idx_vec,
             location_map: visitor.location_map,
             activation_map: visitor.activation_map,
-            region_map: visitor.region_map,
             local_map: visitor.local_map,
             locals_state_at_exit: visitor.locals_state_at_exit,
         }
@@ -184,7 +178,6 @@ struct GatherBorrows<'a, 'gcx: 'tcx, 'tcx: 'a> {
     idx_vec: IndexVec<BorrowIndex, BorrowData<'tcx>>,
     location_map: FxHashMap<Location, BorrowIndex>,
     activation_map: FxHashMap<Location, Vec<BorrowIndex>>,
-    region_map: FxHashMap<RegionVid, FxHashSet<BorrowIndex>>,
     local_map: FxHashMap<mir::Local, FxHashSet<BorrowIndex>>,
 
     /// When we encounter a 2-phase borrow statement, it will always
@@ -229,7 +222,6 @@ impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> {
 
             self.insert_as_pending_if_two_phase(location, &assigned_place, kind, idx);
 
-            self.region_map.entry(region).or_default().insert(idx);
             if let Some(local) = borrowed_place.root_local() {
                 self.local_map.entry(local).or_default().insert(idx);
             }
diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs
index 27bc28ac81d84..3a9e4fc9e4ab9 100644
--- a/src/librustc_mir/dataflow/impls/borrows.rs
+++ b/src/librustc_mir/dataflow/impls/borrows.rs
@@ -246,7 +246,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
                 // re-consider the current implementations of the
                 // propagate_call_return method.
 
-                if let mir::Rvalue::Ref(region, _, ref place) = **rhs {
+                if let mir::Rvalue::Ref(_, _, ref place) = **rhs {
                     if place.ignore_borrow(
                         self.tcx,
                         self.mir,
@@ -258,13 +258,6 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
                         panic!("could not find BorrowIndex for location {:?}", location);
                     });
 
-                    assert!(self.borrow_set.region_map
-                        .get(&region.to_region_vid())
-                        .unwrap_or_else(|| {
-                            panic!("could not find BorrowIndexs for RegionVid {:?}", region);
-                        })
-                        .contains(&index)
-                    );
                     sets.gen(*index);
 
                     // Issue #46746: Two-phase borrows handles

From 6000c2e0e16ee60078a3e2810ff3d26639bdeff5 Mon Sep 17 00:00:00 2001
From: Matthew Jasper <mjjasper1@gmail.com>
Date: Fri, 30 Nov 2018 21:49:43 +0000
Subject: [PATCH 24/45] Use visit_local to find 2PB activations

---
 src/librustc_mir/borrow_check/borrow_set.rs | 110 ++++++++++----------
 1 file changed, 55 insertions(+), 55 deletions(-)

diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs
index a6af79ffbe922..947c32df0f6a3 100644
--- a/src/librustc_mir/borrow_check/borrow_set.rs
+++ b/src/librustc_mir/borrow_check/borrow_set.rs
@@ -230,68 +230,68 @@ impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> {
         self.super_assign(block, assigned_place, rvalue, location)
     }
 
-    fn visit_place(
+    fn visit_local(
         &mut self,
-        place: &mir::Place<'tcx>,
+        temp: &Local,
         context: PlaceContext<'tcx>,
         location: Location,
     ) {
-        self.super_place(place, context, location);
-
-        // We found a use of some temporary TEMP...
-        if let Place::Local(temp) = place {
-            // ... check whether we (earlier) saw a 2-phase borrow like
-            //
-            //     TMP = &mut place
-            if let Some(&borrow_index) = self.pending_activations.get(temp) {
-                let borrow_data = &mut self.idx_vec[borrow_index];
-
-                // Watch out: the use of TMP in the borrow itself
-                // doesn't count as an activation. =)
-                if borrow_data.reserve_location == location &&
-                    context == PlaceContext::MutatingUse(MutatingUseContext::Store)
-                {
-                    return;
-                }
+        if !context.is_use() {
+            return;
+        }
 
-                if let TwoPhaseActivation::ActivatedAt(other_location) =
-                        borrow_data.activation_location {
-                    span_bug!(
-                        self.mir.source_info(location).span,
-                        "found two uses for 2-phase borrow temporary {:?}: \
-                         {:?} and {:?}",
-                        temp,
-                        location,
-                        other_location,
-                    );
-                }
+        // We found a use of some temporary TMP
+        // check whether we (earlier) saw a 2-phase borrow like
+        //
+        //     TMP = &mut place
+        if let Some(&borrow_index) = self.pending_activations.get(temp) {
+            let borrow_data = &mut self.idx_vec[borrow_index];
 
-                // Otherwise, this is the unique later use
-                // that we expect.
-                borrow_data.activation_location = match context {
-                    // The use of TMP in a shared borrow does not
-                    // count as an actual activation.
-                    PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow(..)) |
-                    PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow(..)) =>
-                        TwoPhaseActivation::NotActivated,
-                    _ => {
-                        // Double check: This borrow is indeed a two-phase borrow (that is,
-                        // we are 'transitioning' from `NotActivated` to `ActivatedAt`) and
-                        // we've not found any other activations (checked above).
-                        assert_eq!(
-                            borrow_data.activation_location,
-                            TwoPhaseActivation::NotActivated,
-                            "never found an activation for this borrow!",
-                        );
-
-                        self.activation_map
-                            .entry(location)
-                            .or_default()
-                            .push(borrow_index);
-                        TwoPhaseActivation::ActivatedAt(location)
-                    }
-                };
+            // Watch out: the use of TMP in the borrow itself
+            // doesn't count as an activation. =)
+            if borrow_data.reserve_location == location &&
+                context == PlaceContext::MutatingUse(MutatingUseContext::Store)
+            {
+                return;
             }
+
+            if let TwoPhaseActivation::ActivatedAt(other_location) =
+                    borrow_data.activation_location {
+                span_bug!(
+                    self.mir.source_info(location).span,
+                    "found two uses for 2-phase borrow temporary {:?}: \
+                     {:?} and {:?}",
+                    temp,
+                    location,
+                    other_location,
+                );
+            }
+
+            // Otherwise, this is the unique later use
+            // that we expect.
+            borrow_data.activation_location = match context {
+                // The use of TMP in a shared borrow does not
+                // count as an actual activation.
+                PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow(..)) |
+                PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow(..)) =>
+                    TwoPhaseActivation::NotActivated,
+                _ => {
+                    // Double check: This borrow is indeed a two-phase borrow (that is,
+                    // we are 'transitioning' from `NotActivated` to `ActivatedAt`) and
+                    // we've not found any other activations (checked above).
+                    assert_eq!(
+                        borrow_data.activation_location,
+                        TwoPhaseActivation::NotActivated,
+                        "never found an activation for this borrow!",
+                    );
+
+                    self.activation_map
+                        .entry(location)
+                        .or_default()
+                        .push(borrow_index);
+                    TwoPhaseActivation::ActivatedAt(location)
+                }
+            };
         }
     }
 

From 3b705a0ece15843e6deef6833025f8548f4348c5 Mon Sep 17 00:00:00 2001
From: Oliver Middleton <olliemail27@gmail.com>
Date: Sun, 2 Dec 2018 16:55:00 +0000
Subject: [PATCH 25/45] rustbuild: Fix issues with compiler docs

* Create output directories for crates beforehand so rustdoc uses relative links
* Readd rustc_codegen_ssa
* Don't build out of tree dependencies for rustdoc like we don't for rustc
---
 src/bootstrap/doc.rs | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index f9b19ffb10d69..c1361b5768032 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -696,9 +696,6 @@ impl Step for Rustc {
             return;
         }
 
-        // Build libstd docs so that we generate relative links.
-        builder.ensure(Std { stage, target });
-
         // Build rustc.
         builder.ensure(compile::Rustc { compiler, target });
 
@@ -717,12 +714,16 @@ impl Step for Rustc {
 
         // Find dependencies for top level crates.
         let mut compiler_crates = HashSet::new();
-        for root_crate in &["rustc", "rustc_driver", "rustc_codegen_llvm"] {
+        for root_crate in &["rustc_driver", "rustc_codegen_llvm", "rustc_codegen_ssa"] {
             let interned_root_crate = INTERNER.intern_str(root_crate);
             find_compiler_crates(builder, &interned_root_crate, &mut compiler_crates);
         }
 
         for krate in &compiler_crates {
+            // Create all crate output directories first to make sure rustdoc uses
+            // relative links.
+            // FIXME: Cargo should probably do this itself.
+            t!(fs::create_dir_all(out_dir.join(krate)));
             cargo.arg("-p").arg(krate);
         }
 
@@ -796,8 +797,8 @@ impl Step for Rustdoc {
             return;
         }
 
-        // Build libstd docs so that we generate relative links.
-        builder.ensure(Std { stage, target });
+        // Build rustc docs so that we generate relative links.
+        builder.ensure(Rustc { stage, target });
 
         // Build rustdoc.
         builder.ensure(tool::Rustdoc { host: compiler.host });
@@ -821,6 +822,10 @@ impl Step for Rustdoc {
             &[]
         );
 
+        // Only include compiler crates, no dependencies of those, such as `libc`.
+        cargo.arg("--no-deps");
+        cargo.arg("-p").arg("rustdoc");
+
         cargo.env("RUSTDOCFLAGS", "--document-private-items");
         builder.run(&mut cargo);
     }

From 23abd182d8bdcc82662f6cd5ba6c0c8ab61cce82 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date: Sun, 2 Dec 2018 19:12:37 +0100
Subject: [PATCH 26/45] Fix invalid line number match

---
 src/librustdoc/html/static/rustdoc.css | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index 1ae3b0b88c6dd..e39064b191a77 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -134,7 +134,6 @@ summary {
 
 code, pre {
 	font-family: "Source Code Pro", monospace;
-	white-space: pre-wrap;
 }
 .docblock code, .docblock-short code {
 	border-radius: 3px;
@@ -301,6 +300,7 @@ body:not(.source) .example-wrap {
 
 body:not(.source) .example-wrap > pre.rust {
 	width: 100%;
+	overflow-x: auto;
 }
 
 #search {

From 380dd7d47b574697fe87ef00ad5ffcbb6651c501 Mon Sep 17 00:00:00 2001
From: Thomas de Zeeuw <thomasdezeeuw@gmail.com>
Date: Thu, 15 Nov 2018 16:41:06 +0100
Subject: [PATCH 27/45] Add rc::Weak.ptr_eq

---
 src/liballoc/rc.rs | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index 705345ce963bb..064b3180d4c20 100644
--- a/src/liballoc/rc.rs
+++ b/src/liballoc/rc.rs
@@ -1260,6 +1260,52 @@ impl<T: ?Sized> Weak<T> {
             Some(unsafe { self.ptr.as_ref() })
         }
     }
+
+    /// Returns true if the two `Weak`s point to the same value (not just values
+    /// that compare as equal).
+    ///
+    /// # Notes
+    ///
+    /// Since this compares pointers it means that `Weak::new()` will equal each
+    /// other, even though they don't point to any value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(weak_ptr_eq)]
+    /// use std::rc::{Rc, Weak};
+    ///
+    /// let first_rc = Rc::new(5);
+    /// let first = Rc::downgrade(&first_rc);
+    /// let second = Rc::downgrade(&first_rc);
+    ///
+    /// assert!(Weak::ptr_eq(&first, &second));
+    ///
+    /// let third_rc = Rc::new(5);
+    /// let third = Rc::downgrade(&third_rc);
+    ///
+    /// assert!(!Weak::ptr_eq(&first, &third));
+    /// ```
+    ///
+    /// Comparing `Weak::new`.
+    ///
+    /// ```
+    /// #![feature(weak_ptr_eq)]
+    /// use std::rc::{Rc, Weak};
+    ///
+    /// let first = Weak::new();
+    /// let second = Weak::new();
+    /// assert!(Weak::ptr_eq(&first, &second));
+    ///
+    /// let third_rc = Rc::new(());
+    /// let third = Rc::downgrade(&third_rc);
+    /// assert!(!Weak::ptr_eq(&first, &third));
+    /// ```
+    #[inline]
+    #[unstable(feature = "weak_ptr_eq", issue = "55981")]
+    pub fn ptr_eq(this: &Self, other: &Self) -> bool {
+        this.ptr.as_ptr() == other.ptr.as_ptr()
+    }
 }
 
 #[stable(feature = "rc_weak", since = "1.4.0")]

From d4b41fa0313ace66d5f4e5d4a6201cd3aa81b87d Mon Sep 17 00:00:00 2001
From: Thomas de Zeeuw <thomasdezeeuw@gmail.com>
Date: Thu, 15 Nov 2018 20:24:02 +0100
Subject: [PATCH 28/45] Add sync::Weak::ptr_eq

---
 src/liballoc/sync.rs | 47 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs
index 4f4031e3c4e32..0a397f79103db 100644
--- a/src/liballoc/sync.rs
+++ b/src/liballoc/sync.rs
@@ -1130,6 +1130,53 @@ impl<T: ?Sized> Weak<T> {
             Some(unsafe { self.ptr.as_ref() })
         }
     }
+
+    /// Returns true if the two `Weak`s point to the same value (not just values
+    /// that compare as equal).
+    ///
+    /// # Notes
+    ///
+    /// Since this compares pointers it means that `Weak::new()` will equal each
+    /// other, even though they don't point to any value.
+    ///
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(weak_ptr_eq)]
+    /// use std::sync::{Arc, Weak};
+    ///
+    /// let first_rc = Arc::new(5);
+    /// let first = Arc::downgrade(&first_rc);
+    /// let second = Arc::downgrade(&first_rc);
+    ///
+    /// assert!(Weak::ptr_eq(&first, &second));
+    ///
+    /// let third_rc = Arc::new(5);
+    /// let third = Arc::downgrade(&third_rc);
+    ///
+    /// assert!(!Weak::ptr_eq(&first, &third));
+    /// ```
+    ///
+    /// Comparing `Weak::new`.
+    ///
+    /// ```
+    /// #![feature(weak_ptr_eq)]
+    /// use std::sync::{Arc, Weak};
+    ///
+    /// let first = Weak::new();
+    /// let second = Weak::new();
+    /// assert!(Weak::ptr_eq(&first, &second));
+    ///
+    /// let third_rc = Arc::new(());
+    /// let third = Arc::downgrade(&third_rc);
+    /// assert!(!Weak::ptr_eq(&first, &third));
+    /// ```
+    #[inline]
+    #[unstable(feature = "weak_ptr_eq", issue = "55981")]
+    pub fn ptr_eq(this: &Self, other: &Self) -> bool {
+        this.ptr.as_ptr() == other.ptr.as_ptr()
+    }
 }
 
 #[stable(feature = "arc_weak", since = "1.4.0")]

From 38e21f92f1c09a597788062045b1e1d8c879e4f2 Mon Sep 17 00:00:00 2001
From: Thomas de Zeeuw <thomasdezeeuw@gmail.com>
Date: Fri, 23 Nov 2018 12:26:13 +0100
Subject: [PATCH 29/45] Fix link in Weak::new

---
 src/liballoc/rc.rs | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index 064b3180d4c20..d81b8a1974dca 100644
--- a/src/liballoc/rc.rs
+++ b/src/liballoc/rc.rs
@@ -1187,8 +1187,9 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Weak<U>> for Weak<T> {}
 
 impl<T> Weak<T> {
     /// Constructs a new `Weak<T>`, without allocating any memory.
-    /// Calling [`upgrade`][Weak::upgrade] on the return value always gives [`None`].
+    /// Calling [`upgrade`] on the return value always gives [`None`].
     ///
+    /// [`upgrade`]: #method.upgrade
     /// [`None`]: ../../std/option/enum.Option.html
     ///
     /// # Examples

From 1fb82b5a038428901818acfdca15a1d61c241146 Mon Sep 17 00:00:00 2001
From: Oliver Scherer <github35764891676564198441@oli-obk.de>
Date: Mon, 3 Dec 2018 14:44:58 +0100
Subject: [PATCH 30/45] Handle existential types in dead code analysis

---
 src/librustc/middle/dead.rs                     |  1 +
 src/test/ui/existential_types/private_unused.rs | 13 +++++++++++++
 2 files changed, 14 insertions(+)
 create mode 100644 src/test/ui/existential_types/private_unused.rs

diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index 282b5d13e2c61..bb7a6a6ee7b72 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -166,6 +166,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
                     hir::ItemKind::Fn(..)
                     | hir::ItemKind::Ty(..)
                     | hir::ItemKind::Static(..)
+                    | hir::ItemKind::Existential(..)
                     | hir::ItemKind::Const(..) => {
                         intravisit::walk_item(self, &item);
                     }
diff --git a/src/test/ui/existential_types/private_unused.rs b/src/test/ui/existential_types/private_unused.rs
new file mode 100644
index 0000000000000..736d812bc0aff
--- /dev/null
+++ b/src/test/ui/existential_types/private_unused.rs
@@ -0,0 +1,13 @@
+// compile-pass
+
+#[deny(warnings)]
+
+enum Empty { }
+trait Bar<T> {}
+impl Bar<Empty> for () {}
+
+fn boo() -> impl Bar<Empty> {}
+
+fn main() {
+    boo();
+}

From 651373c13d9b9d06af6150bfc897d0f97fc4d919 Mon Sep 17 00:00:00 2001
From: ljedrz <ljedrz@gmail.com>
Date: Mon, 3 Dec 2018 17:33:06 +0100
Subject: [PATCH 31/45] data_structures: remove tuple_slice

---
 src/librustc_data_structures/lib.rs         |  1 -
 src/librustc_data_structures/tuple_slice.rs | 70 ---------------------
 2 files changed, 71 deletions(-)
 delete mode 100644 src/librustc_data_structures/tuple_slice.rs

diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs
index 96cb235a93362..8e0ecb70c6896 100644
--- a/src/librustc_data_structures/lib.rs
+++ b/src/librustc_data_structures/lib.rs
@@ -81,7 +81,6 @@ pub mod sync;
 pub mod tiny_list;
 pub mod thin_vec;
 pub mod transitive_relation;
-pub mod tuple_slice;
 pub use ena::unify;
 pub mod vec_linked_list;
 pub mod work_queue;
diff --git a/src/librustc_data_structures/tuple_slice.rs b/src/librustc_data_structures/tuple_slice.rs
deleted file mode 100644
index b7c71dd366469..0000000000000
--- a/src/librustc_data_structures/tuple_slice.rs
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use std::slice;
-
-/// Allows to view uniform tuples as slices
-pub trait TupleSlice<T> {
-    fn as_slice(&self) -> &[T];
-    fn as_mut_slice(&mut self) -> &mut [T];
-}
-
-macro_rules! impl_tuple_slice {
-    ($tuple_type:ty, $size:expr) => {
-        impl<T> TupleSlice<T> for $tuple_type {
-            fn as_slice(&self) -> &[T] {
-                unsafe {
-                    let ptr = &self.0 as *const T;
-                    slice::from_raw_parts(ptr, $size)
-                }
-            }
-
-            fn as_mut_slice(&mut self) -> &mut [T] {
-                unsafe {
-                    let ptr = &mut self.0 as *mut T;
-                    slice::from_raw_parts_mut(ptr, $size)
-                }
-            }
-        }
-    }
-}
-
-impl_tuple_slice!((T, T), 2);
-impl_tuple_slice!((T, T, T), 3);
-impl_tuple_slice!((T, T, T, T), 4);
-impl_tuple_slice!((T, T, T, T, T), 5);
-impl_tuple_slice!((T, T, T, T, T, T), 6);
-impl_tuple_slice!((T, T, T, T, T, T, T), 7);
-impl_tuple_slice!((T, T, T, T, T, T, T, T), 8);
-
-#[test]
-fn test_sliced_tuples() {
-    let t2 = (100, 101);
-    assert_eq!(t2.as_slice(), &[100, 101]);
-
-    let t3 = (102, 103, 104);
-    assert_eq!(t3.as_slice(), &[102, 103, 104]);
-
-    let t4 = (105, 106, 107, 108);
-    assert_eq!(t4.as_slice(), &[105, 106, 107, 108]);
-
-    let t5 = (109, 110, 111, 112, 113);
-    assert_eq!(t5.as_slice(), &[109, 110, 111, 112, 113]);
-
-    let t6 = (114, 115, 116, 117, 118, 119);
-    assert_eq!(t6.as_slice(), &[114, 115, 116, 117, 118, 119]);
-
-    let t7 = (120, 121, 122, 123, 124, 125, 126);
-    assert_eq!(t7.as_slice(), &[120, 121, 122, 123, 124, 125, 126]);
-
-    let t8 = (127, 128, 129, 130, 131, 132, 133, 134);
-    assert_eq!(t8.as_slice(), &[127, 128, 129, 130, 131, 132, 133, 134]);
-
-}

From 9c8802dc01692cbb684b8759c083b71b27102c29 Mon Sep 17 00:00:00 2001
From: Mark Mansi <markm@cs.wisc.edu>
Date: Sat, 1 Dec 2018 18:16:08 -0600
Subject: [PATCH 32/45] Explain raw identifer syntax

---
 src/libcore/macros.rs | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs
index 8b1855800c2fd..a7fd3a08b4a66 100644
--- a/src/libcore/macros.rs
+++ b/src/libcore/macros.rs
@@ -238,6 +238,8 @@ macro_rules! debug_assert_ne {
 /// with converting downstream errors.
 ///
 /// The `?` operator was added to replace `try!` and should be used instead.
+/// Furthermore, `try` is a reserved word in Rust 2018, so if you must use
+/// it, you will need to use the raw-identifier syntax: `r#try`.
 ///
 /// `try!` matches the given [`Result`]. In case of the `Ok` variant, the
 /// expression has the value of the wrapped value.

From 0b40be696eb1f1756d38261de538015e8cfe7772 Mon Sep 17 00:00:00 2001
From: Mark Mansi <markm@cs.wisc.edu>
Date: Sat, 1 Dec 2018 18:24:11 -0600
Subject: [PATCH 33/45] link to raw identifiers

---
 src/libcore/macros.rs | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs
index a7fd3a08b4a66..5ba0e949483ae 100644
--- a/src/libcore/macros.rs
+++ b/src/libcore/macros.rs
@@ -239,7 +239,9 @@ macro_rules! debug_assert_ne {
 ///
 /// The `?` operator was added to replace `try!` and should be used instead.
 /// Furthermore, `try` is a reserved word in Rust 2018, so if you must use
-/// it, you will need to use the raw-identifier syntax: `r#try`.
+/// it, you will need to use the [raw-identifier syntax][ris]: `r#try`.
+///
+/// [ris]: https://doc.rust-lang.org/nightly/rust-by-example/compatibility/raw_identifiers.html
 ///
 /// `try!` matches the given [`Result`]. In case of the `Ok` variant, the
 /// expression has the value of the wrapped value.

From 3f253f53946398199277cfb6e3af7c05b5ed3b4f Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date: Mon, 3 Dec 2018 23:04:59 +0100
Subject: [PATCH 34/45] Improve filter test

---
 src/test/rustdoc-js/filter-crate.js | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/src/test/rustdoc-js/filter-crate.js b/src/test/rustdoc-js/filter-crate.js
index 69c959a6ef21c..97ecc607f4764 100644
--- a/src/test/rustdoc-js/filter-crate.js
+++ b/src/test/rustdoc-js/filter-crate.js
@@ -8,13 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// should-fail
+// exact-check
 
-const QUERY = 'string';
+const QUERY = 'hashmap';
 const FILTER_CRATE = 'core';
 
 const EXPECTED = {
     'others': [
-        { 'path': 'std::collections', 'name': 'VecDeque' },
     ],
 };

From 65aa0a6249b7d7afddbd7d5b9cf4c8c68575e334 Mon Sep 17 00:00:00 2001
From: Shotaro Yamada <sinkuu@sinkuu.xyz>
Date: Wed, 28 Nov 2018 12:19:22 +0900
Subject: [PATCH 35/45] Remove redundant clone

---
 src/librustc_resolve/build_reduced_graph.rs | 2 +-
 src/libsyntax/ext/tt/macro_parser.rs        | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 0fa41cb484fc9..da4cd73923ede 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -318,7 +318,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
                         // This particular use tree
                         &tree, id, &prefix, true,
                         // The whole `use` item
-                        parent_scope.clone(), item, ty::Visibility::Invisible, root_span,
+                        parent_scope, item, ty::Visibility::Invisible, root_span,
                     );
                 }
             }
diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs
index 8fd9590a66415..68d94b43dba2c 100644
--- a/src/libsyntax/ext/tt/macro_parser.rs
+++ b/src/libsyntax/ext/tt/macro_parser.rs
@@ -309,7 +309,7 @@ fn create_matches(len: usize) -> Box<[Rc<NamedMatchVec>]> {
         vec![]
     } else {
         let empty_matches = Rc::new(SmallVec::new());
-        vec![empty_matches.clone(); len]
+        vec![empty_matches; len]
     }.into_boxed_slice()
 }
 

From bc7c3dc71de785da813784bafaa490f12d4d7cfe Mon Sep 17 00:00:00 2001
From: Shotaro Yamada <sinkuu@sinkuu.xyz>
Date: Sat, 1 Dec 2018 08:39:51 +0900
Subject: [PATCH 36/45] sort_by_cached_key -> sort_by

---
 src/librustc_mir/monomorphize/partitioning.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs
index 3a6ee6da42215..528942df29fee 100644
--- a/src/librustc_mir/monomorphize/partitioning.rs
+++ b/src/librustc_mir/monomorphize/partitioning.rs
@@ -585,7 +585,7 @@ fn merge_codegen_units<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>,
     // smallest into each other) we're sure to start off with a deterministic
     // order (sorted by name). This'll mean that if two cgus have the same size
     // the stable sort below will keep everything nice and deterministic.
-    codegen_units.sort_by_key(|cgu| cgu.name().clone());
+    codegen_units.sort_by_key(|cgu| *cgu.name());
 
     // Merge the two smallest codegen units until the target size is reached.
     while codegen_units.len() > target_cgu_count {
@@ -985,7 +985,7 @@ fn collect_and_partition_mono_items<'a, 'tcx>(
                 output.push_str(" @@");
                 let mut empty = Vec::new();
                 let cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty);
-                cgus.as_mut_slice().sort_by_cached_key(|&(ref name, _)| name.clone());
+                cgus.sort_by_key(|(name, _)| *name);
                 cgus.dedup();
                 for &(ref cgu_name, (linkage, _)) in cgus.iter() {
                     output.push_str(" ");

From 6fab3f9c693e1699d9056ec64e3c950ad3f7bfb3 Mon Sep 17 00:00:00 2001
From: Dale Wijnand <dale.wijnand@gmail.com>
Date: Tue, 4 Dec 2018 07:48:20 +0000
Subject: [PATCH 37/45] Make ptr::hash take a raw painter like ptr::eq

---
 src/libcore/ptr.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index 0213b310efaa3..606dd765ce1d2 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -2534,7 +2534,7 @@ pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool {
 /// assert_eq!(actual, expected);
 /// ```
 #[unstable(feature = "ptr_hash", reason = "newly added", issue = "56286")]
-pub fn hash<T, S: hash::Hasher>(hashee: &T, into: &mut S) {
+pub fn hash<T, S: hash::Hasher>(hashee: *const T, into: &mut S) {
     use hash::Hash;
     NonNull::from(hashee).hash(into)
 }

From ad765695d1a831b9e1c11102a1e8680af86a89bd Mon Sep 17 00:00:00 2001
From: Dale Wijnand <dale.wijnand@gmail.com>
Date: Tue, 4 Dec 2018 08:06:26 +0000
Subject: [PATCH 38/45] Fix ptr::hash, just hash the raw pointer

---
 src/libcore/ptr.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index 606dd765ce1d2..4be89180d677d 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -2536,7 +2536,7 @@ pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool {
 #[unstable(feature = "ptr_hash", reason = "newly added", issue = "56286")]
 pub fn hash<T, S: hash::Hasher>(hashee: *const T, into: &mut S) {
     use hash::Hash;
-    NonNull::from(hashee).hash(into)
+    hashee.hash(into);
 }
 
 // Impls for function pointers

From 450a8a6f354ac9b19d5980837ea0f34cd6c7ece6 Mon Sep 17 00:00:00 2001
From: Bastian Gruber <gruberbastian@me.com>
Date: Tue, 4 Dec 2018 10:10:07 +0100
Subject: [PATCH 39/45] Add extra comment slash

---
 src/libstd/path.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libstd/path.rs b/src/libstd/path.rs
index dcd02ac59b6c8..9fad40c564944 100644
--- a/src/libstd/path.rs
+++ b/src/libstd/path.rs
@@ -1410,7 +1410,7 @@ impl From<PathBuf> for Box<Path> {
     /// Converts a `PathBuf` into a `Box<Path>`
     ///
     /// This conversion currently should not allocate memory,
-    // but this behavior is not guaranteed on all platforms or in all future versions.
+    /// but this behavior is not guaranteed on all platforms or in all future versions.
     fn from(p: PathBuf) -> Box<Path> {
         p.into_boxed_path()
     }

From 8c4129cd9ae079fc010b8e3d73a72659b2f0a986 Mon Sep 17 00:00:00 2001
From: ljedrz <ljedrz@gmail.com>
Date: Tue, 4 Dec 2018 10:21:42 +0100
Subject: [PATCH 40/45] cleanup: remove static lifetimes from consts in libstd

---
 src/libstd/env.rs                           |  42 ++--
 src/libstd/ffi/c_str.rs                     |   4 +-
 src/libstd/keyword_docs.rs                  |   2 +-
 src/libstd/sys/cloudabi/shims/env.rs        |  14 +-
 src/libstd/sys/redox/env.rs                 |  14 +-
 src/libstd/sys/redox/path.rs                |   2 +-
 src/libstd/sys/redox/process.rs             |   2 +-
 src/libstd/sys/unix/env.rs                  | 224 ++++++++++----------
 src/libstd/sys/unix/path.rs                 |   2 +-
 src/libstd/sys/unix/process/process_unix.rs |   2 +-
 src/libstd/sys/wasm/env.rs                  |  14 +-
 src/libstd/sys/wasm/path.rs                 |   2 +-
 src/libstd/sys/windows/env.rs               |  14 +-
 src/libstd/sys/windows/os.rs                |   4 +-
 src/libstd/sys/windows/path.rs              |   2 +-
 src/libstd/sys_common/wtf8.rs               |   2 +-
 16 files changed, 173 insertions(+), 173 deletions(-)

diff --git a/src/libstd/env.rs b/src/libstd/env.rs
index 9066c0b769479..d14efa2e3c76d 100644
--- a/src/libstd/env.rs
+++ b/src/libstd/env.rs
@@ -828,7 +828,7 @@ pub mod consts {
     /// - s390x
     /// - sparc64
     #[stable(feature = "env", since = "1.0.0")]
-    pub const ARCH: &'static str = super::arch::ARCH;
+    pub const ARCH: &str = super::arch::ARCH;
 
     /// The family of the operating system. Example value is `unix`.
     ///
@@ -837,7 +837,7 @@ pub mod consts {
     /// - unix
     /// - windows
     #[stable(feature = "env", since = "1.0.0")]
-    pub const FAMILY: &'static str = os::FAMILY;
+    pub const FAMILY: &str = os::FAMILY;
 
     /// A string describing the specific operating system in use.
     /// Example value is `linux`.
@@ -856,7 +856,7 @@ pub mod consts {
     /// - android
     /// - windows
     #[stable(feature = "env", since = "1.0.0")]
-    pub const OS: &'static str = os::OS;
+    pub const OS: &str = os::OS;
 
     /// Specifies the filename prefix used for shared libraries on this
     /// platform. Example value is `lib`.
@@ -866,7 +866,7 @@ pub mod consts {
     /// - lib
     /// - `""` (an empty string)
     #[stable(feature = "env", since = "1.0.0")]
-    pub const DLL_PREFIX: &'static str = os::DLL_PREFIX;
+    pub const DLL_PREFIX: &str = os::DLL_PREFIX;
 
     /// Specifies the filename suffix used for shared libraries on this
     /// platform. Example value is `.so`.
@@ -877,7 +877,7 @@ pub mod consts {
     /// - .dylib
     /// - .dll
     #[stable(feature = "env", since = "1.0.0")]
-    pub const DLL_SUFFIX: &'static str = os::DLL_SUFFIX;
+    pub const DLL_SUFFIX: &str = os::DLL_SUFFIX;
 
     /// Specifies the file extension used for shared libraries on this
     /// platform that goes after the dot. Example value is `so`.
@@ -888,7 +888,7 @@ pub mod consts {
     /// - dylib
     /// - dll
     #[stable(feature = "env", since = "1.0.0")]
-    pub const DLL_EXTENSION: &'static str = os::DLL_EXTENSION;
+    pub const DLL_EXTENSION: &str = os::DLL_EXTENSION;
 
     /// Specifies the filename suffix used for executable binaries on this
     /// platform. Example value is `.exe`.
@@ -900,7 +900,7 @@ pub mod consts {
     /// - .pexe
     /// - `""` (an empty string)
     #[stable(feature = "env", since = "1.0.0")]
-    pub const EXE_SUFFIX: &'static str = os::EXE_SUFFIX;
+    pub const EXE_SUFFIX: &str = os::EXE_SUFFIX;
 
     /// Specifies the file extension, if any, used for executable binaries
     /// on this platform. Example value is `exe`.
@@ -910,72 +910,72 @@ pub mod consts {
     /// - exe
     /// - `""` (an empty string)
     #[stable(feature = "env", since = "1.0.0")]
-    pub const EXE_EXTENSION: &'static str = os::EXE_EXTENSION;
+    pub const EXE_EXTENSION: &str = os::EXE_EXTENSION;
 }
 
 #[cfg(target_arch = "x86")]
 mod arch {
-    pub const ARCH: &'static str = "x86";
+    pub const ARCH: &str = "x86";
 }
 
 #[cfg(target_arch = "x86_64")]
 mod arch {
-    pub const ARCH: &'static str = "x86_64";
+    pub const ARCH: &str = "x86_64";
 }
 
 #[cfg(target_arch = "arm")]
 mod arch {
-    pub const ARCH: &'static str = "arm";
+    pub const ARCH: &str = "arm";
 }
 
 #[cfg(target_arch = "aarch64")]
 mod arch {
-    pub const ARCH: &'static str = "aarch64";
+    pub const ARCH: &str = "aarch64";
 }
 
 #[cfg(target_arch = "mips")]
 mod arch {
-    pub const ARCH: &'static str = "mips";
+    pub const ARCH: &str = "mips";
 }
 
 #[cfg(target_arch = "mips64")]
 mod arch {
-    pub const ARCH: &'static str = "mips64";
+    pub const ARCH: &str = "mips64";
 }
 
 #[cfg(target_arch = "powerpc")]
 mod arch {
-    pub const ARCH: &'static str = "powerpc";
+    pub const ARCH: &str = "powerpc";
 }
 
 #[cfg(target_arch = "powerpc64")]
 mod arch {
-    pub const ARCH: &'static str = "powerpc64";
+    pub const ARCH: &str = "powerpc64";
 }
 
 #[cfg(target_arch = "s390x")]
 mod arch {
-    pub const ARCH: &'static str = "s390x";
+    pub const ARCH: &str = "s390x";
 }
 
 #[cfg(target_arch = "sparc64")]
 mod arch {
-    pub const ARCH: &'static str = "sparc64";
+    pub const ARCH: &str = "sparc64";
 }
 
 #[cfg(target_arch = "le32")]
 mod arch {
-    pub const ARCH: &'static str = "le32";
+    pub const ARCH: &str = "le32";
 }
 
 #[cfg(target_arch = "asmjs")]
 mod arch {
-    pub const ARCH: &'static str = "asmjs";
+    pub const ARCH: &str = "asmjs";
 }
 
 #[cfg(target_arch = "wasm32")]
 mod arch {
-    pub const ARCH: &'static str = "wasm32";
+    pub const ARCH: &str = "wasm32";
 }
 
 #[cfg(test)]
diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs
index 66718b95408ca..7c7f83967e051 100644
--- a/src/libstd/ffi/c_str.rs
+++ b/src/libstd/ffi/c_str.rs
@@ -671,7 +671,7 @@ impl fmt::Debug for CStr {
 #[stable(feature = "cstr_default", since = "1.10.0")]
 impl<'a> Default for &'a CStr {
     fn default() -> &'a CStr {
-        const SLICE: &'static [c_char] = &[0];
+        const SLICE: &[c_char] = &[0];
         unsafe { CStr::from_ptr(SLICE.as_ptr()) }
     }
 }
@@ -1475,7 +1475,7 @@ mod tests {
 
     #[test]
     fn cstr_const_constructor() {
-        const CSTR: &'static CStr = unsafe {
+        const CSTR: &CStr = unsafe {
             CStr::from_bytes_with_nul_unchecked(b"Hello, world!\0")
         };
 
diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs
index 13cf3133dcd12..c1eaf29bb4407 100644
--- a/src/libstd/keyword_docs.rs
+++ b/src/libstd/keyword_docs.rs
@@ -65,7 +65,7 @@ mod as_keyword { }
 /// look like this:
 ///
 /// ```rust
-/// const WORDS: &'static str = "hello rust!";
+/// const WORDS: &str = "hello rust!";
 /// ```
 ///
 /// Thanks to static lifetime elision, you usually don't have to explicitly use 'static:
diff --git a/src/libstd/sys/cloudabi/shims/env.rs b/src/libstd/sys/cloudabi/shims/env.rs
index 31777aa94bcd4..c7691e3b2df29 100644
--- a/src/libstd/sys/cloudabi/shims/env.rs
+++ b/src/libstd/sys/cloudabi/shims/env.rs
@@ -9,11 +9,11 @@
 // except according to those terms.
 
 pub mod os {
-    pub const FAMILY: &'static str = "cloudabi";
-    pub const OS: &'static str = "cloudabi";
-    pub const DLL_PREFIX: &'static str = "lib";
-    pub const DLL_SUFFIX: &'static str = ".so";
-    pub const DLL_EXTENSION: &'static str = "so";
-    pub const EXE_SUFFIX: &'static str = "";
-    pub const EXE_EXTENSION: &'static str = "";
+    pub const FAMILY: &str = "cloudabi";
+    pub const OS: &str = "cloudabi";
+    pub const DLL_PREFIX: &str = "lib";
+    pub const DLL_SUFFIX: &str = ".so";
+    pub const DLL_EXTENSION: &str = "so";
+    pub const EXE_SUFFIX: &str = "";
+    pub const EXE_EXTENSION: &str = "";
 }
diff --git a/src/libstd/sys/redox/env.rs b/src/libstd/sys/redox/env.rs
index 669b7520df846..75e35046fb725 100644
--- a/src/libstd/sys/redox/env.rs
+++ b/src/libstd/sys/redox/env.rs
@@ -9,11 +9,11 @@
 // except according to those terms.
 
 pub mod os {
-    pub const FAMILY: &'static str = "redox";
-    pub const OS: &'static str = "redox";
-    pub const DLL_PREFIX: &'static str = "lib";
-    pub const DLL_SUFFIX: &'static str = ".so";
-    pub const DLL_EXTENSION: &'static str = "so";
-    pub const EXE_SUFFIX: &'static str = "";
-    pub const EXE_EXTENSION: &'static str = "";
+    pub const FAMILY: &str = "redox";
+    pub const OS: &str = "redox";
+    pub const DLL_PREFIX: &str = "lib";
+    pub const DLL_SUFFIX: &str = ".so";
+    pub const DLL_EXTENSION: &str = "so";
+    pub const EXE_SUFFIX: &str = "";
+    pub const EXE_EXTENSION: &str = "";
 }
diff --git a/src/libstd/sys/redox/path.rs b/src/libstd/sys/redox/path.rs
index e6a267dd5d913..b1a4ed30404c0 100644
--- a/src/libstd/sys/redox/path.rs
+++ b/src/libstd/sys/redox/path.rs
@@ -35,5 +35,5 @@ pub fn parse_prefix(path: &OsStr) -> Option<Prefix> {
     }
 }
 
-pub const MAIN_SEP_STR: &'static str = "/";
+pub const MAIN_SEP_STR: &str = "/";
 pub const MAIN_SEP: char = '/';
diff --git a/src/libstd/sys/redox/process.rs b/src/libstd/sys/redox/process.rs
index 4370c1e05027b..8f6d83c544a54 100644
--- a/src/libstd/sys/redox/process.rs
+++ b/src/libstd/sys/redox/process.rs
@@ -143,7 +143,7 @@ impl Command {
 
     pub fn spawn(&mut self, default: Stdio, needs_stdin: bool)
                  -> io::Result<(Process, StdioPipes)> {
-         const CLOEXEC_MSG_FOOTER: &'static [u8] = b"NOEX";
+         const CLOEXEC_MSG_FOOTER: &[u8] = b"NOEX";
 
          if self.saw_nul {
              return Err(io::Error::new(ErrorKind::InvalidInput,
diff --git a/src/libstd/sys/unix/env.rs b/src/libstd/sys/unix/env.rs
index ad116c57f557e..1b6838f0295ef 100644
--- a/src/libstd/sys/unix/env.rs
+++ b/src/libstd/sys/unix/env.rs
@@ -10,176 +10,176 @@
 
 #[cfg(target_os = "linux")]
 pub mod os {
-    pub const FAMILY: &'static str = "unix";
-    pub const OS: &'static str = "linux";
-    pub const DLL_PREFIX: &'static str = "lib";
-    pub const DLL_SUFFIX: &'static str = ".so";
-    pub const DLL_EXTENSION: &'static str = "so";
-    pub const EXE_SUFFIX: &'static str = "";
-    pub const EXE_EXTENSION: &'static str = "";
+    pub const FAMILY: &str = "unix";
+    pub const OS: &str = "linux";
+    pub const DLL_PREFIX: &str = "lib";
+    pub const DLL_SUFFIX: &str = ".so";
+    pub const DLL_EXTENSION: &str = "so";
+    pub const EXE_SUFFIX: &str = "";
+    pub const EXE_EXTENSION: &str = "";
 }
 
 #[cfg(target_os = "macos")]
 pub mod os {
-    pub const FAMILY: &'static str = "unix";
-    pub const OS: &'static str = "macos";
-    pub const DLL_PREFIX: &'static str = "lib";
-    pub const DLL_SUFFIX: &'static str = ".dylib";
-    pub const DLL_EXTENSION: &'static str = "dylib";
-    pub const EXE_SUFFIX: &'static str = "";
-    pub const EXE_EXTENSION: &'static str = "";
+    pub const FAMILY: &str = "unix";
+    pub const OS: &str = "macos";
+    pub const DLL_PREFIX: &str = "lib";
+    pub const DLL_SUFFIX: &str = ".dylib";
+    pub const DLL_EXTENSION: &str = "dylib";
+    pub const EXE_SUFFIX: &str = "";
+    pub const EXE_EXTENSION: &str = "";
 }
 
 #[cfg(target_os = "ios")]
 pub mod os {
-    pub const FAMILY: &'static str = "unix";
-    pub const OS: &'static str = "ios";
-    pub const DLL_PREFIX: &'static str = "lib";
-    pub const DLL_SUFFIX: &'static str = ".dylib";
-    pub const DLL_EXTENSION: &'static str = "dylib";
-    pub const EXE_SUFFIX: &'static str = "";
-    pub const EXE_EXTENSION: &'static str = "";
+    pub const FAMILY: &str = "unix";
+    pub const OS: &str = "ios";
+    pub const DLL_PREFIX: &str = "lib";
+    pub const DLL_SUFFIX: &str = ".dylib";
+    pub const DLL_EXTENSION: &str = "dylib";
+    pub const EXE_SUFFIX: &str = "";
+    pub const EXE_EXTENSION: &str = "";
 }
 
 #[cfg(target_os = "freebsd")]
 pub mod os {
-    pub const FAMILY: &'static str = "unix";
-    pub const OS: &'static str = "freebsd";
-    pub const DLL_PREFIX: &'static str = "lib";
-    pub const DLL_SUFFIX: &'static str = ".so";
-    pub const DLL_EXTENSION: &'static str = "so";
-    pub const EXE_SUFFIX: &'static str = "";
-    pub const EXE_EXTENSION: &'static str = "";
+    pub const FAMILY: &str = "unix";
+    pub const OS: &str = "freebsd";
+    pub const DLL_PREFIX: &str = "lib";
+    pub const DLL_SUFFIX: &str = ".so";
+    pub const DLL_EXTENSION: &str = "so";
+    pub const EXE_SUFFIX: &str = "";
+    pub const EXE_EXTENSION: &str = "";
 }
 
 #[cfg(target_os = "dragonfly")]
 pub mod os {
-    pub const FAMILY: &'static str = "unix";
-    pub const OS: &'static str = "dragonfly";
-    pub const DLL_PREFIX: &'static str = "lib";
-    pub const DLL_SUFFIX: &'static str = ".so";
-    pub const DLL_EXTENSION: &'static str = "so";
-    pub const EXE_SUFFIX: &'static str = "";
-    pub const EXE_EXTENSION: &'static str = "";
+    pub const FAMILY: &str = "unix";
+    pub const OS: &str = "dragonfly";
+    pub const DLL_PREFIX: &str = "lib";
+    pub const DLL_SUFFIX: &str = ".so";
+    pub const DLL_EXTENSION: &str = "so";
+    pub const EXE_SUFFIX: &str = "";
+    pub const EXE_EXTENSION: &str = "";
 }
 
 #[cfg(target_os = "bitrig")]
 pub mod os {
-    pub const FAMILY: &'static str = "unix";
-    pub const OS: &'static str = "bitrig";
-    pub const DLL_PREFIX: &'static str = "lib";
-    pub const DLL_SUFFIX: &'static str = ".so";
-    pub const DLL_EXTENSION: &'static str = "so";
-    pub const EXE_SUFFIX: &'static str = "";
-    pub const EXE_EXTENSION: &'static str = "";
+    pub const FAMILY: &str = "unix";
+    pub const OS: &str = "bitrig";
+    pub const DLL_PREFIX: &str = "lib";
+    pub const DLL_SUFFIX: &str = ".so";
+    pub const DLL_EXTENSION: &str = "so";
+    pub const EXE_SUFFIX: &str = "";
+    pub const EXE_EXTENSION: &str = "";
 }
 
 #[cfg(target_os = "netbsd")]
 pub mod os {
-    pub const FAMILY: &'static str = "unix";
-    pub const OS: &'static str = "netbsd";
-    pub const DLL_PREFIX: &'static str = "lib";
-    pub const DLL_SUFFIX: &'static str = ".so";
-    pub const DLL_EXTENSION: &'static str = "so";
-    pub const EXE_SUFFIX: &'static str = "";
-    pub const EXE_EXTENSION: &'static str = "";
+    pub const FAMILY: &str = "unix";
+    pub const OS: &str = "netbsd";
+    pub const DLL_PREFIX: &str = "lib";
+    pub const DLL_SUFFIX: &str = ".so";
+    pub const DLL_EXTENSION: &str = "so";
+    pub const EXE_SUFFIX: &str = "";
+    pub const EXE_EXTENSION: &str = "";
 }
 
 #[cfg(target_os = "openbsd")]
 pub mod os {
-    pub const FAMILY: &'static str = "unix";
-    pub const OS: &'static str = "openbsd";
-    pub const DLL_PREFIX: &'static str = "lib";
-    pub const DLL_SUFFIX: &'static str = ".so";
-    pub const DLL_EXTENSION: &'static str = "so";
-    pub const EXE_SUFFIX: &'static str = "";
-    pub const EXE_EXTENSION: &'static str = "";
+    pub const FAMILY: &str = "unix";
+    pub const OS: &str = "openbsd";
+    pub const DLL_PREFIX: &str = "lib";
+    pub const DLL_SUFFIX: &str = ".so";
+    pub const DLL_EXTENSION: &str = "so";
+    pub const EXE_SUFFIX: &str = "";
+    pub const EXE_EXTENSION: &str = "";
 }
 
 #[cfg(target_os = "android")]
 pub mod os {
-    pub const FAMILY: &'static str = "unix";
-    pub const OS: &'static str = "android";
-    pub const DLL_PREFIX: &'static str = "lib";
-    pub const DLL_SUFFIX: &'static str = ".so";
-    pub const DLL_EXTENSION: &'static str = "so";
-    pub const EXE_SUFFIX: &'static str = "";
-    pub const EXE_EXTENSION: &'static str = "";
+    pub const FAMILY: &str = "unix";
+    pub const OS: &str = "android";
+    pub const DLL_PREFIX: &str = "lib";
+    pub const DLL_SUFFIX: &str = ".so";
+    pub const DLL_EXTENSION: &str = "so";
+    pub const EXE_SUFFIX: &str = "";
+    pub const EXE_EXTENSION: &str = "";
 }
 
 #[cfg(target_os = "solaris")]
 pub mod os {
-    pub const FAMILY: &'static str = "unix";
-    pub const OS: &'static str = "solaris";
-    pub const DLL_PREFIX: &'static str = "lib";
-    pub const DLL_SUFFIX: &'static str = ".so";
-    pub const DLL_EXTENSION: &'static str = "so";
-    pub const EXE_SUFFIX: &'static str = "";
-    pub const EXE_EXTENSION: &'static str = "";
+    pub const FAMILY: &str = "unix";
+    pub const OS: &str = "solaris";
+    pub const DLL_PREFIX: &str = "lib";
+    pub const DLL_SUFFIX: &str = ".so";
+    pub const DLL_EXTENSION: &str = "so";
+    pub const EXE_SUFFIX: &str = "";
+    pub const EXE_EXTENSION: &str = "";
 }
 
 #[cfg(target_os = "haiku")]
 pub mod os {
-    pub const FAMILY: &'static str = "unix";
-    pub const OS: &'static str = "haiku";
-    pub const DLL_PREFIX: &'static str = "lib";
-    pub const DLL_SUFFIX: &'static str = ".so";
-    pub const DLL_EXTENSION: &'static str = "so";
-    pub const EXE_SUFFIX: &'static str = "";
-    pub const EXE_EXTENSION: &'static str = "";
+    pub const FAMILY: &str = "unix";
+    pub const OS: &str = "haiku";
+    pub const DLL_PREFIX: &str = "lib";
+    pub const DLL_SUFFIX: &str = ".so";
+    pub const DLL_EXTENSION: &str = "so";
+    pub const EXE_SUFFIX: &str = "";
+    pub const EXE_EXTENSION: &str = "";
 }
 
 #[cfg(all(target_os = "emscripten", target_arch = "asmjs"))]
 pub mod os {
-    pub const FAMILY: &'static str = "unix";
-    pub const OS: &'static str = "emscripten";
-    pub const DLL_PREFIX: &'static str = "lib";
-    pub const DLL_SUFFIX: &'static str = ".so";
-    pub const DLL_EXTENSION: &'static str = "so";
-    pub const EXE_SUFFIX: &'static str = ".js";
-    pub const EXE_EXTENSION: &'static str = "js";
+    pub const FAMILY: &str = "unix";
+    pub const OS: &str = "emscripten";
+    pub const DLL_PREFIX: &str = "lib";
+    pub const DLL_SUFFIX: &str = ".so";
+    pub const DLL_EXTENSION: &str = "so";
+    pub const EXE_SUFFIX: &str = ".js";
+    pub const EXE_EXTENSION: &str = "js";
 }
 
 #[cfg(all(target_os = "emscripten", target_arch = "wasm32"))]
 pub mod os {
-    pub const FAMILY: &'static str = "unix";
-    pub const OS: &'static str = "emscripten";
-    pub const DLL_PREFIX: &'static str = "lib";
-    pub const DLL_SUFFIX: &'static str = ".so";
-    pub const DLL_EXTENSION: &'static str = "so";
-    pub const EXE_SUFFIX: &'static str = ".js";
-    pub const EXE_EXTENSION: &'static str = "js";
+    pub const FAMILY: &str = "unix";
+    pub const OS: &str = "emscripten";
+    pub const DLL_PREFIX: &str = "lib";
+    pub const DLL_SUFFIX: &str = ".so";
+    pub const DLL_EXTENSION: &str = "so";
+    pub const EXE_SUFFIX: &str = ".js";
+    pub const EXE_EXTENSION: &str = "js";
 }
 
 #[cfg(target_os = "fuchsia")]
 pub mod os {
-    pub const FAMILY: &'static str = "unix";
-    pub const OS: &'static str = "fuchsia";
-    pub const DLL_PREFIX: &'static str = "lib";
-    pub const DLL_SUFFIX: &'static str = ".so";
-    pub const DLL_EXTENSION: &'static str = "so";
-    pub const EXE_SUFFIX: &'static str = "";
-    pub const EXE_EXTENSION: &'static str = "";
+    pub const FAMILY: &str = "unix";
+    pub const OS: &str = "fuchsia";
+    pub const DLL_PREFIX: &str = "lib";
+    pub const DLL_SUFFIX: &str = ".so";
+    pub const DLL_EXTENSION: &str = "so";
+    pub const EXE_SUFFIX: &str = "";
+    pub const EXE_EXTENSION: &str = "";
 }
 
 #[cfg(target_os = "l4re")]
 pub mod os {
-    pub const FAMILY: &'static str = "unix";
-    pub const OS: &'static str = "l4re";
-    pub const DLL_PREFIX: &'static str = "lib";
-    pub const DLL_SUFFIX: &'static str = ".so";
-    pub const DLL_EXTENSION: &'static str = "so";
-    pub const EXE_SUFFIX: &'static str = "";
-    pub const EXE_EXTENSION: &'static str = "";
+    pub const FAMILY: &str = "unix";
+    pub const OS: &str = "l4re";
+    pub const DLL_PREFIX: &str = "lib";
+    pub const DLL_SUFFIX: &str = ".so";
+    pub const DLL_EXTENSION: &str = "so";
+    pub const EXE_SUFFIX: &str = "";
+    pub const EXE_EXTENSION: &str = "";
 }
 
 #[cfg(target_os = "hermit")]
 pub mod os {
-    pub const FAMILY: &'static str = "unix";
-    pub const OS: &'static str = "hermit";
-    pub const DLL_PREFIX: &'static str = "lib";
-    pub const DLL_SUFFIX: &'static str = ".so";
-    pub const DLL_EXTENSION: &'static str = "so";
-    pub const EXE_SUFFIX: &'static str = "";
-    pub const EXE_EXTENSION: &'static str = "";
+    pub const FAMILY: &str = "unix";
+    pub const OS: &str = "hermit";
+    pub const DLL_PREFIX: &str = "lib";
+    pub const DLL_SUFFIX: &str = ".so";
+    pub const DLL_EXTENSION: &str = "so";
+    pub const EXE_SUFFIX: &str = "";
+    pub const EXE_EXTENSION: &str = "";
 }
diff --git a/src/libstd/sys/unix/path.rs b/src/libstd/sys/unix/path.rs
index bf9af7a4353a8..834b4b448dc8a 100644
--- a/src/libstd/sys/unix/path.rs
+++ b/src/libstd/sys/unix/path.rs
@@ -25,5 +25,5 @@ pub fn parse_prefix(_: &OsStr) -> Option<Prefix> {
     None
 }
 
-pub const MAIN_SEP_STR: &'static str = "/";
+pub const MAIN_SEP_STR: &str = "/";
 pub const MAIN_SEP: char = '/';
diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs
index bfbf12f34ee37..3248f42446071 100644
--- a/src/libstd/sys/unix/process/process_unix.rs
+++ b/src/libstd/sys/unix/process/process_unix.rs
@@ -22,7 +22,7 @@ use sys;
 impl Command {
     pub fn spawn(&mut self, default: Stdio, needs_stdin: bool)
                  -> io::Result<(Process, StdioPipes)> {
-        const CLOEXEC_MSG_FOOTER: &'static [u8] = b"NOEX";
+        const CLOEXEC_MSG_FOOTER: &[u8] = b"NOEX";
 
         let envp = self.capture_env();
 
diff --git a/src/libstd/sys/wasm/env.rs b/src/libstd/sys/wasm/env.rs
index 1422042bd0228..09235a944eec0 100644
--- a/src/libstd/sys/wasm/env.rs
+++ b/src/libstd/sys/wasm/env.rs
@@ -9,11 +9,11 @@
 // except according to those terms.
 
 pub mod os {
-    pub const FAMILY: &'static str = "";
-    pub const OS: &'static str = "";
-    pub const DLL_PREFIX: &'static str = "";
-    pub const DLL_SUFFIX: &'static str = ".wasm";
-    pub const DLL_EXTENSION: &'static str = "wasm";
-    pub const EXE_SUFFIX: &'static str = ".wasm";
-    pub const EXE_EXTENSION: &'static str = "wasm";
+    pub const FAMILY: &str = "";
+    pub const OS: &str = "";
+    pub const DLL_PREFIX: &str = "";
+    pub const DLL_SUFFIX: &str = ".wasm";
+    pub const DLL_EXTENSION: &str = "wasm";
+    pub const EXE_SUFFIX: &str = ".wasm";
+    pub const EXE_EXTENSION: &str = "wasm";
 }
diff --git a/src/libstd/sys/wasm/path.rs b/src/libstd/sys/wasm/path.rs
index 395b8c1e40e98..fcc9d617a876a 100644
--- a/src/libstd/sys/wasm/path.rs
+++ b/src/libstd/sys/wasm/path.rs
@@ -25,5 +25,5 @@ pub fn parse_prefix(_: &OsStr) -> Option<Prefix> {
     None
 }
 
-pub const MAIN_SEP_STR: &'static str = "/";
+pub const MAIN_SEP_STR: &str = "/";
 pub const MAIN_SEP: char = '/';
diff --git a/src/libstd/sys/windows/env.rs b/src/libstd/sys/windows/env.rs
index e6d74895774ce..4523df04f247d 100644
--- a/src/libstd/sys/windows/env.rs
+++ b/src/libstd/sys/windows/env.rs
@@ -9,11 +9,11 @@
 // except according to those terms.
 
 pub mod os {
-    pub const FAMILY: &'static str = "windows";
-    pub const OS: &'static str = "windows";
-    pub const DLL_PREFIX: &'static str = "";
-    pub const DLL_SUFFIX: &'static str = ".dll";
-    pub const DLL_EXTENSION: &'static str = "dll";
-    pub const EXE_SUFFIX: &'static str = ".exe";
-    pub const EXE_EXTENSION: &'static str = "exe";
+    pub const FAMILY: &str = "windows";
+    pub const OS: &str = "windows";
+    pub const DLL_PREFIX: &str = "";
+    pub const DLL_SUFFIX: &str = ".dll";
+    pub const DLL_EXTENSION: &str = "dll";
+    pub const EXE_SUFFIX: &str = ".exe";
+    pub const EXE_EXTENSION: &str = "exe";
 }
diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs
index 29ea82c2053cd..4d7b7236c59c6 100644
--- a/src/libstd/sys/windows/os.rs
+++ b/src/libstd/sys/windows/os.rs
@@ -48,8 +48,8 @@ pub fn error_string(mut errnum: i32) -> String {
         // `[MS-ERREF]`: https://msdn.microsoft.com/en-us/library/cc231198.aspx
         if (errnum & c::FACILITY_NT_BIT as i32) != 0 {
             // format according to https://support.microsoft.com/en-us/help/259693
-            const NTDLL_DLL: &'static [u16] = &['N' as _, 'T' as _, 'D' as _, 'L' as _, 'L' as _,
-                                                '.' as _, 'D' as _, 'L' as _, 'L' as _, 0];
+            const NTDLL_DLL: &[u16] = &['N' as _, 'T' as _, 'D' as _, 'L' as _, 'L' as _,
+                                        '.' as _, 'D' as _, 'L' as _, 'L' as _, 0];
             module = c::GetModuleHandleW(NTDLL_DLL.as_ptr());
 
             if module != ptr::null_mut() {
diff --git a/src/libstd/sys/windows/path.rs b/src/libstd/sys/windows/path.rs
index 98d62a0c953a6..c5524a74d8370 100644
--- a/src/libstd/sys/windows/path.rs
+++ b/src/libstd/sys/windows/path.rs
@@ -102,5 +102,5 @@ pub fn parse_prefix<'a>(path: &'a OsStr) -> Option<Prefix> {
     }
 }
 
-pub const MAIN_SEP_STR: &'static str = "\\";
+pub const MAIN_SEP_STR: &str = "\\";
 pub const MAIN_SEP: char = '\\';
diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs
index 19ce932aa1233..3530b7af9ad05 100644
--- a/src/libstd/sys_common/wtf8.rs
+++ b/src/libstd/sys_common/wtf8.rs
@@ -40,7 +40,7 @@ use str;
 use sync::Arc;
 use sys_common::AsInner;
 
-const UTF8_REPLACEMENT_CHARACTER: &'static str = "\u{FFFD}";
+const UTF8_REPLACEMENT_CHARACTER: &str = "\u{FFFD}";
 
 /// A Unicode code point: from U+0000 to U+10FFFF.
 ///

From e41e85cb5ca7f37eb8b1615a724ab016721d4237 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date: Tue, 4 Dec 2018 11:33:57 +0100
Subject: [PATCH 41/45] Fix line numbers display

---
 src/librustdoc/html/static/rustdoc.css | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index c50c968f36002..19e8e8c4c9538 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -282,7 +282,7 @@ nav.sub {
 	padding-left: 0;
 }
 
-:not(.source) .example-wrap {
+.rustdoc:not(.source) .example-wrap {
 	display: inline-flex;
 	margin-bottom: 10px;
 }
@@ -300,7 +300,7 @@ nav.sub {
 	text-align: right;
 }
 
-:not(.source) .example-wrap > pre.rust {
+.rustdoc:not(.source) .example-wrap > pre.rust {
 	width: 100%;
 }
 

From 9012af6f19d999869824e3b933de5f7b30986877 Mon Sep 17 00:00:00 2001
From: Corey Farwell <coreyf@rwell.org>
Date: Tue, 20 Nov 2018 23:01:56 -0500
Subject: [PATCH 42/45] Utilize `?` instead of `return None`.

---
 src/libcore/str/mod.rs                        |  7 +++----
 src/librustc/middle/region.rs                 |  5 +----
 src/librustc/session/search_paths.rs          | 11 +++++-----
 .../persist/work_product.rs                   |  8 ++------
 src/librustc_mir/borrow_check/prefixes.rs     |  5 +----
 src/librustdoc/clean/mod.rs                   | 10 ++--------
 src/librustdoc/html/render.rs                 |  8 ++++----
 src/libstd/sys/windows/path.rs                |  5 +----
 .../run-pass/impl-trait/example-calendar.rs   |  5 +----
 src/tools/compiletest/src/errors.rs           |  5 +----
 src/tools/compiletest/src/header.rs           | 20 ++++---------------
 src/tools/linkchecker/main.rs                 |  5 +----
 12 files changed, 26 insertions(+), 68 deletions(-)

diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index a2782dd8e2e43..71aec7126e08d 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -536,10 +536,9 @@ fn next_code_point_reverse<'a, I>(bytes: &mut I) -> Option<u32>
     where I: DoubleEndedIterator<Item = &'a u8>,
 {
     // Decode UTF-8
-    let w = match bytes.next_back() {
-        None => return None,
-        Some(&next_byte) if next_byte < 128 => return Some(next_byte as u32),
-        Some(&back_byte) => back_byte,
+    let w = match *bytes.next_back()? {
+        next_byte if next_byte < 128 => return Some(next_byte as u32),
+        back_byte => back_byte,
     };
 
     // Multibyte case follows
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index d00fbdeca21aa..774b5f0ab11ca 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -592,10 +592,7 @@ impl<'tcx> ScopeTree {
                 return Some(scope.item_local_id());
             }
 
-            match self.opt_encl_scope(scope) {
-                None => return None,
-                Some(parent) => scope = parent,
-            }
+            scope = self.opt_encl_scope(scope)?;
         }
     }
 
diff --git a/src/librustc/session/search_paths.rs b/src/librustc/session/search_paths.rs
index 768d4f1e5fb65..6b0a8a0af2b9d 100644
--- a/src/librustc/session/search_paths.rs
+++ b/src/librustc/session/search_paths.rs
@@ -67,14 +67,13 @@ impl<'a> Iterator for Iter<'a> {
 
     fn next(&mut self) -> Option<(&'a Path, PathKind)> {
         loop {
-            match self.iter.next() {
-                Some(&(kind, ref p)) if self.kind == PathKind::All ||
-                                        kind == PathKind::All ||
-                                        kind == self.kind => {
+            match *self.iter.next()? {
+                (kind, ref p) if self.kind == PathKind::All ||
+                                  kind == PathKind::All ||
+                                  kind == self.kind => {
                     return Some((p, kind))
                 }
-                Some(..) => {}
-                None => return None,
+                _ => {}
             }
         }
     }
diff --git a/src/librustc_incremental/persist/work_product.rs b/src/librustc_incremental/persist/work_product.rs
index cfe59b1f67262..ddd28eb5393ec 100644
--- a/src/librustc_incremental/persist/work_product.rs
+++ b/src/librustc_incremental/persist/work_product.rs
@@ -29,7 +29,7 @@ pub fn copy_cgu_workproducts_to_incr_comp_cache_dir(
         return None
     }
 
-    let saved_files: Option<Vec<_>> =
+    let saved_files =
         files.iter()
              .map(|&(kind, ref path)| {
                  let extension = match kind {
@@ -51,11 +51,7 @@ pub fn copy_cgu_workproducts_to_incr_comp_cache_dir(
                      }
                  }
              })
-             .collect();
-    let saved_files = match saved_files {
-        None => return None,
-        Some(v) => v,
-    };
+             .collect::<Option<Vec<_>>>()?;
 
     let work_product = WorkProduct {
         cgu_name: cgu_name.to_string(),
diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs
index f73e08eb13521..7d583b4f54191 100644
--- a/src/librustc_mir/borrow_check/prefixes.rs
+++ b/src/librustc_mir/borrow_check/prefixes.rs
@@ -87,10 +87,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
 impl<'cx, 'gcx, 'tcx> Iterator for Prefixes<'cx, 'gcx, 'tcx> {
     type Item = &'cx Place<'tcx>;
     fn next(&mut self) -> Option<Self::Item> {
-        let mut cursor = match self.next {
-            None => return None,
-            Some(place) => place,
-        };
+        let mut cursor = self.next?;
 
         // Post-processing `place`: Enqueue any remaining
         // work. Also, `place` may not be a prefix itself, but
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 88240e844edc2..fa879e6309c97 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -3923,10 +3923,7 @@ pub fn path_to_def_local(tcx: &TyCtxt, path: &[&str]) -> Option<DefId> {
     let mut path_it = path.iter().peekable();
 
     loop {
-        let segment = match path_it.next() {
-            Some(segment) => segment,
-            None => return None,
-        };
+        let segment = path_it.next()?;
 
         for item_id in mem::replace(&mut items, HirVec::new()).iter() {
             let item = tcx.hir.expect_item(item_id.id);
@@ -3961,10 +3958,7 @@ pub fn path_to_def(tcx: &TyCtxt, path: &[&str]) -> Option<DefId> {
         let mut path_it = path.iter().skip(1).peekable();
 
         loop {
-            let segment = match path_it.next() {
-                Some(segment) => segment,
-                None => return None,
-            };
+            let segment = path_it.next()?;
 
             for item in mem::replace(&mut items, Lrc::new(vec![])).iter() {
                 if item.ident.name == *segment {
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 8b35ede4a02c0..07ff8791c34ab 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -2079,13 +2079,13 @@ impl<'a> Item<'a> {
                 return None;
             }
         } else {
-            let (krate, src_root) = match cache.extern_locations.get(&self.item.def_id.krate) {
-                Some(&(ref name, ref src, Local)) => (name, src),
-                Some(&(ref name, ref src, Remote(ref s))) => {
+            let (krate, src_root) = match *cache.extern_locations.get(&self.item.def_id.krate)? {
+                (ref name, ref src, Local) => (name, src),
+                (ref name, ref src, Remote(ref s)) => {
                     root = s.to_string();
                     (name, src)
                 }
-                Some(&(_, _, Unknown)) | None => return None,
+                (_, _, Unknown) => return None,
             };
 
             clean_srcpath(&src_root, file, false, |component| {
diff --git a/src/libstd/sys/windows/path.rs b/src/libstd/sys/windows/path.rs
index 98d62a0c953a6..ff910a50226f2 100644
--- a/src/libstd/sys/windows/path.rs
+++ b/src/libstd/sys/windows/path.rs
@@ -91,10 +91,7 @@ pub fn parse_prefix<'a>(path: &'a OsStr) -> Option<Prefix> {
     }
 
     fn parse_two_comps(mut path: &[u8], f: fn(u8) -> bool) -> Option<(&[u8], &[u8])> {
-        let first = match path.iter().position(|x| f(*x)) {
-            None => return None,
-            Some(x) => &path[..x],
-        };
+        let first = &path[..path.iter().position(|x| f(*x))?];
         path = &path[(first.len() + 1)..];
         let idx = path.iter().position(|x| f(*x));
         let second = &path[..idx.unwrap_or(path.len())];
diff --git a/src/test/run-pass/impl-trait/example-calendar.rs b/src/test/run-pass/impl-trait/example-calendar.rs
index 6cf06d1562104..42a94fca36c1a 100644
--- a/src/test/run-pass/impl-trait/example-calendar.rs
+++ b/src/test/run-pass/impl-trait/example-calendar.rs
@@ -753,10 +753,7 @@ where It: Iterator {
     type Item = Vec<It::Item>;
 
     fn next(&mut self) -> Option<Vec<It::Item>> {
-        let first = match self.it.next() {
-            Some(e) => e,
-            None => return None
-        };
+        let first = self.it.next()?;
 
         let mut result = Vec::with_capacity(self.n);
         result.push(first);
diff --git a/src/tools/compiletest/src/errors.rs b/src/tools/compiletest/src/errors.rs
index dd2e5557c16d4..8d20a9e271705 100644
--- a/src/tools/compiletest/src/errors.rs
+++ b/src/tools/compiletest/src/errors.rs
@@ -119,10 +119,7 @@ fn parse_expected(
     line: &str,
     tag: &str,
 ) -> Option<(WhichLine, Error)> {
-    let start = match line.find(tag) {
-        Some(i) => i,
-        None => return None,
-    };
+    let start = line.find(tag)?;
     let (follow, adjusts) = if line[start + tag.len()..].chars().next().unwrap() == '|' {
         (true, 0)
     } else {
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 06eeef61a194d..eeb3f5e6f4441 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -684,14 +684,8 @@ impl Config {
 
     fn parse_custom_normalization(&self, mut line: &str, prefix: &str) -> Option<(String, String)> {
         if self.parse_cfg_name_directive(line, prefix) == ParsedNameDirective::Match {
-            let from = match parse_normalization_string(&mut line) {
-                Some(s) => s,
-                None => return None,
-            };
-            let to = match parse_normalization_string(&mut line) {
-                Some(s) => s,
-                None => return None,
-            };
+            let from = parse_normalization_string(&mut line)?;
+            let to = parse_normalization_string(&mut line)?;
             Some((from, to))
         } else {
             None
@@ -850,14 +844,8 @@ fn expand_variables(mut value: String, config: &Config) -> String {
 /// ```
 fn parse_normalization_string(line: &mut &str) -> Option<String> {
     // FIXME support escapes in strings.
-    let begin = match line.find('"') {
-        Some(i) => i + 1,
-        None => return None,
-    };
-    let end = match line[begin..].find('"') {
-        Some(i) => i + begin,
-        None => return None,
-    };
+    let begin = line.find('"')? + 1;
+    let end = line[begin..].find('"')? + begin;
     let result = line[begin..end].to_owned();
     *line = &line[end + 1..];
     Some(result)
diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs
index 41ad4e7180e60..8993092333536 100644
--- a/src/tools/linkchecker/main.rs
+++ b/src/tools/linkchecker/main.rs
@@ -332,10 +332,7 @@ fn maybe_redirect(source: &str) -> Option<String> {
     const REDIRECT: &'static str = "<p>Redirecting to <a href=";
 
     let mut lines = source.lines();
-    let redirect_line = match lines.nth(6) {
-        Some(l) => l,
-        None => return None,
-    };
+    let redirect_line = lines.nth(6)?;
 
     redirect_line.find(REDIRECT).map(|i| {
         let rest = &redirect_line[(i + REDIRECT.len() + 1)..];

From 56ace3e870352f1b6c49426b1e40a6260b94b260 Mon Sep 17 00:00:00 2001
From: John Heitmann <jheitmann@gmail.com>
Date: Tue, 4 Dec 2018 13:59:27 -0800
Subject: [PATCH 43/45] Added a bare-bones eslint config (removing jslint)

This change removes the small bit of jslint config, replacing it
with eslint. I've currently configured eslint to mostly only report
the more serious of lints, although there are still some style nits
turned on.

Upcoming changes will start fixing lints.
---
 src/librustdoc/html/static/.eslintrc.js     | 21 +++++++++++++++++++++
 src/librustdoc/html/static/main.js          |  8 ++++++--
 src/librustdoc/html/static/source-script.js |  6 ++++++
 src/librustdoc/html/static/storage.js       |  3 +++
 4 files changed, 36 insertions(+), 2 deletions(-)
 create mode 100644 src/librustdoc/html/static/.eslintrc.js

diff --git a/src/librustdoc/html/static/.eslintrc.js b/src/librustdoc/html/static/.eslintrc.js
new file mode 100644
index 0000000000000..fbfb0e76494b4
--- /dev/null
+++ b/src/librustdoc/html/static/.eslintrc.js
@@ -0,0 +1,21 @@
+module.exports = {
+    "env": {
+        "browser": true,
+        "es6": true
+    },
+    "extends": "eslint:recommended",
+    "parserOptions": {
+        "ecmaVersion": 2015,
+        "sourceType": "module"
+    },
+    "rules": {
+        "linebreak-style": [
+            "error",
+            "unix"
+        ],
+        "semi": [
+            "error",
+            "always"
+        ]
+    }
+};
\ No newline at end of file
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index 781f99cd6932f..c82d171b69f70 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -10,8 +10,12 @@
  * except according to those terms.
  */
 
-/*jslint browser: true, es5: true */
-/*globals $: true, rootPath: true */
+// From rust:
+/* global ALIASES, currentCrate, rootPath */
+
+// Local js definitions:
+/* global addClass, getCurrentValue, hasClass */
+/* global isHidden onEach, removeClass, updateLocalStorage */
 
 if (!String.prototype.startsWith) {
     String.prototype.startsWith = function(searchString, position) {
diff --git a/src/librustdoc/html/static/source-script.js b/src/librustdoc/html/static/source-script.js
index 1db8218dae6f2..03b0955a34c31 100644
--- a/src/librustdoc/html/static/source-script.js
+++ b/src/librustdoc/html/static/source-script.js
@@ -10,6 +10,12 @@
  * except according to those terms.
  */
 
+// From rust:
+/* global sourcesIndex */
+
+// Local js definitions:
+/* global addClass, getCurrentValue, hasClass, removeClass, updateLocalStorage */
+
 function getCurrentFilePath() {
     var parts = window.location.pathname.split("/");
     var rootPathParts = window.rootPath.split("/");
diff --git a/src/librustdoc/html/static/storage.js b/src/librustdoc/html/static/storage.js
index 150001a751445..e8f0c03d91aa6 100644
--- a/src/librustdoc/html/static/storage.js
+++ b/src/librustdoc/html/static/storage.js
@@ -10,6 +10,9 @@
  * except according to those terms.
  */
 
+// From rust:
+/* global resourcesSuffix */
+
 var currentTheme = document.getElementById("themeStyle");
 var mainTheme = document.getElementById("mainThemeStyle");
 

From 5d7cf59e94ea1ee5480ac083e5b6949deec9fb2f Mon Sep 17 00:00:00 2001
From: John Heitmann <jheitmann@gmail.com>
Date: Tue, 4 Dec 2018 16:13:04 -0800
Subject: [PATCH 44/45] Added trailing newline

---
 src/librustdoc/html/static/.eslintrc.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/librustdoc/html/static/.eslintrc.js b/src/librustdoc/html/static/.eslintrc.js
index fbfb0e76494b4..c7af41ac969ce 100644
--- a/src/librustdoc/html/static/.eslintrc.js
+++ b/src/librustdoc/html/static/.eslintrc.js
@@ -18,4 +18,4 @@ module.exports = {
             "always"
         ]
     }
-};
\ No newline at end of file
+};

From 3512fb046799fe02555b12d1e180d0ef83aba849 Mon Sep 17 00:00:00 2001
From: John-John Tedro <udoprog@tedro.se>
Date: Wed, 5 Dec 2018 02:48:18 +0100
Subject: [PATCH 45/45] Avoid extra copy and syscall in std::env::current_exe

---
 src/libstd/sys/unix/os.rs | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs
index b387a8d59a56d..03e81a720dc64 100644
--- a/src/libstd/sys/unix/os.rs
+++ b/src/libstd/sys/unix/os.rs
@@ -283,11 +283,14 @@ pub fn current_exe() -> io::Result<PathBuf> {
 
 #[cfg(any(target_os = "linux", target_os = "android", target_os = "emscripten"))]
 pub fn current_exe() -> io::Result<PathBuf> {
-    let selfexe = PathBuf::from("/proc/self/exe");
-    if selfexe.exists() {
-        ::fs::read_link(selfexe)
-    } else {
-        Err(io::Error::new(io::ErrorKind::Other, "no /proc/self/exe available. Is /proc mounted?"))
+    match ::fs::read_link("/proc/self/exe") {
+        Err(ref e) if e.kind() == io::ErrorKind::NotFound => {
+            Err(io::Error::new(
+                io::ErrorKind::Other,
+                "no /proc/self/exe available. Is /proc mounted?"
+            ))
+        },
+        other => other,
     }
 }