diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index 850b80e42801b..6d79e662a4279 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -1217,6 +1217,11 @@ extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) {
     return LLVMBFloatTypeKind;
   case Type::X86_AMXTyID:
     return LLVMX86_AMXTypeKind;
+#if LLVM_VERSION_GE(15, 0)
+  case Type::DXILPointerTyID:
+    report_fatal_error("Rust does not support DirectX typed pointers.");
+    break;
+#endif
   }
   report_fatal_error("Unhandled TypeID.");
 }
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 9ea66c0b59d9f..21b888c25c25f 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -1319,7 +1319,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                 | PathSource::Struct
                 | PathSource::TupleStruct(..) => false,
             };
-            let mut error = false;
+            let mut res = LifetimeRes::Error;
             for rib in self.lifetime_ribs.iter().rev() {
                 match rib.kind {
                     // In create-parameter mode we error here because we don't want to support
@@ -1329,7 +1329,6 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                     //     impl Foo for std::cell::Ref<u32> // note lack of '_
                     //     async fn foo(_: std::cell::Ref<u32>) { ... }
                     LifetimeRibKind::AnonymousCreateParameter(_) => {
-                        error = true;
                         break;
                     }
                     // `PassThrough` is the normal case.
@@ -1338,19 +1337,21 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                     // `PathSegment`, for which there is no associated `'_` or `&T` with no explicit
                     // lifetime. Instead, we simply create an implicit lifetime, which will be checked
                     // later, at which point a suitable error will be emitted.
-                    LifetimeRibKind::AnonymousPassThrough(..)
-                    | LifetimeRibKind::AnonymousReportError
-                    | LifetimeRibKind::Item => break,
+                    LifetimeRibKind::AnonymousPassThrough(binder) => {
+                        res = LifetimeRes::Anonymous { binder, elided: true };
+                        break;
+                    }
+                    LifetimeRibKind::AnonymousReportError | LifetimeRibKind::Item => {
+                        // FIXME(cjgillot) This resolution is wrong, but this does not matter
+                        // since these cases are erroneous anyway.  Lifetime resolution should
+                        // emit a "missing lifetime specifier" diagnostic.
+                        res = LifetimeRes::Anonymous { binder: DUMMY_NODE_ID, elided: true };
+                        break;
+                    }
                     _ => {}
                 }
             }
 
-            let res = if error {
-                LifetimeRes::Error
-            } else {
-                LifetimeRes::Anonymous { binder: segment_id, elided: true }
-            };
-
             let node_ids = self.r.next_node_ids(expected_lifetimes);
             self.record_lifetime_res(
                 segment_id,
@@ -1374,7 +1375,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                 // originating from macros, since the segment's span might be from a macro arg.
                 segment.ident.span.find_ancestor_inside(path_span).unwrap_or(path_span)
             };
-            if error {
+            if let LifetimeRes::Error = res {
                 let sess = self.r.session;
                 let mut err = rustc_errors::struct_span_err!(
                     sess,
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index 95177102dcf86..460b5c18fc1b4 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -1102,7 +1102,19 @@ impl FilePathMapping {
         //       take precedence.
         for &(ref from, ref to) in self.mapping.iter().rev() {
             if let Ok(rest) = path.strip_prefix(from) {
-                return (to.join(rest), true);
+                let remapped = if rest.as_os_str().is_empty() {
+                    // This is subtle, joining an empty path onto e.g. `foo/bar` will
+                    // result in `foo/bar/`, that is, there'll be an additional directory
+                    // separator at the end. This can lead to duplicated directory separators
+                    // in remapped paths down the line.
+                    // So, if we have an exact match, we just return that without a call
+                    // to `Path::join()`.
+                    to.clone()
+                } else {
+                    to.join(rest)
+                };
+
+                return (remapped, true);
             }
         }
 
diff --git a/compiler/rustc_span/src/source_map/tests.rs b/compiler/rustc_span/src/source_map/tests.rs
index f13979941abee..481e015c66c25 100644
--- a/compiler/rustc_span/src/source_map/tests.rs
+++ b/compiler/rustc_span/src/source_map/tests.rs
@@ -312,3 +312,83 @@ impl SourceMapExtension for SourceMap {
         }
     }
 }
+
+fn map_path_prefix(mapping: &FilePathMapping, path: &str) -> String {
+    // It's important that we convert to a string here because that's what
+    // later stages do too (e.g. in the backend), and comparing `Path` values
+    // won't catch some differences at the string level, e.g. "abc" and "abc/"
+    // compare as equal.
+    mapping.map_prefix(path.into()).0.to_string_lossy().to_string()
+}
+
+#[cfg(unix)]
+#[test]
+fn path_prefix_remapping() {
+    // Relative to relative
+    {
+        let mapping = &FilePathMapping::new(vec![("abc/def".into(), "foo".into())]);
+
+        assert_eq!(map_path_prefix(mapping, "abc/def/src/main.rs"), "foo/src/main.rs");
+        assert_eq!(map_path_prefix(mapping, "abc/def"), "foo");
+    }
+
+    // Relative to absolute
+    {
+        let mapping = &FilePathMapping::new(vec![("abc/def".into(), "/foo".into())]);
+
+        assert_eq!(map_path_prefix(mapping, "abc/def/src/main.rs"), "/foo/src/main.rs");
+        assert_eq!(map_path_prefix(mapping, "abc/def"), "/foo");
+    }
+
+    // Absolute to relative
+    {
+        let mapping = &FilePathMapping::new(vec![("/abc/def".into(), "foo".into())]);
+
+        assert_eq!(map_path_prefix(mapping, "/abc/def/src/main.rs"), "foo/src/main.rs");
+        assert_eq!(map_path_prefix(mapping, "/abc/def"), "foo");
+    }
+
+    // Absolute to absolute
+    {
+        let mapping = &FilePathMapping::new(vec![("/abc/def".into(), "/foo".into())]);
+
+        assert_eq!(map_path_prefix(mapping, "/abc/def/src/main.rs"), "/foo/src/main.rs");
+        assert_eq!(map_path_prefix(mapping, "/abc/def"), "/foo");
+    }
+}
+
+#[cfg(windows)]
+#[test]
+fn path_prefix_remapping_from_relative2() {
+    // Relative to relative
+    {
+        let mapping = &FilePathMapping::new(vec![("abc\\def".into(), "foo".into())]);
+
+        assert_eq!(map_path_prefix(mapping, "abc\\def\\src\\main.rs"), "foo\\src\\main.rs");
+        assert_eq!(map_path_prefix(mapping, "abc\\def"), "foo");
+    }
+
+    // Relative to absolute
+    {
+        let mapping = &FilePathMapping::new(vec![("abc\\def".into(), "X:\\foo".into())]);
+
+        assert_eq!(map_path_prefix(mapping, "abc\\def\\src\\main.rs"), "X:\\foo\\src\\main.rs");
+        assert_eq!(map_path_prefix(mapping, "abc\\def"), "X:\\foo");
+    }
+
+    // Absolute to relative
+    {
+        let mapping = &FilePathMapping::new(vec![("X:\\abc\\def".into(), "foo".into())]);
+
+        assert_eq!(map_path_prefix(mapping, "X:\\abc\\def\\src\\main.rs"), "foo\\src\\main.rs");
+        assert_eq!(map_path_prefix(mapping, "X:\\abc\\def"), "foo");
+    }
+
+    // Absolute to absolute
+    {
+        let mapping = &FilePathMapping::new(vec![("X:\\abc\\def".into(), "X:\\foo".into())]);
+
+        assert_eq!(map_path_prefix(mapping, "X:\\abc\\def\\src\\main.rs"), "X:\\foo\\src\\main.rs");
+        assert_eq!(map_path_prefix(mapping, "X:\\abc\\def"), "X:\\foo");
+    }
+}
diff --git a/src/doc/unstable-book/src/compiler-flags/cf-protection.md b/src/doc/unstable-book/src/compiler-flags/cf-protection.md
index cc580ca9b4232..ab698c82ba922 100644
--- a/src/doc/unstable-book/src/compiler-flags/cf-protection.md
+++ b/src/doc/unstable-book/src/compiler-flags/cf-protection.md
@@ -17,7 +17,7 @@ standard library does not ship with CET enabled by default, so you may need to r
 modules with a `cargo` command like:
 
 ```sh
-$ RUSTFLAGS="-Z cf-protection=full" RUSTC="rustc-custom" cargo +nightly build -Z build-std --target x86_64-unknown-linux-gnu
+$ RUSTFLAGS="-Z cf-protection=full" cargo +nightly build -Z build-std --target x86_64-unknown-linux-gnu
 ```
 
 ### Detection
diff --git a/src/librustdoc/html/static/js/externs.js b/src/librustdoc/html/static/js/externs.js
index 0fe0fdadbd210..de881dbd0812a 100644
--- a/src/librustdoc/html/static/js/externs.js
+++ b/src/librustdoc/html/static/js/externs.js
@@ -1,9 +1,12 @@
 // This file contains type definitions that are processed by the Closure Compiler but are
 // not put into the JavaScript we include as part of the documentation. It is used for
 // type checking. See README.md in this directory for more info.
+/* eslint-env es6 */
+/* eslint no-var: "error" */
+/* eslint prefer-const: "error" */
 
 /* eslint-disable */
-var searchState;
+let searchState;
 function initSearch(searchIndex){}
 
 /**
@@ -15,7 +18,7 @@ function initSearch(searchIndex){}
  *     generics: Array<QueryElement>,
  * }}
  */
-var QueryElement;
+let QueryElement;
 
 /**
  * @typedef {{
@@ -25,7 +28,7 @@ var QueryElement;
  *      userQuery: string,
  * }}
  */
-var ParserState;
+let ParserState;
 
 /**
  * @typedef {{
@@ -38,7 +41,7 @@ var ParserState;
  *     foundElems: number,
  * }}
  */
-var ParsedQuery;
+let ParsedQuery;
 
 /**
  * @typedef {{
@@ -53,7 +56,7 @@ var ParsedQuery;
  *    type: (Array<?>|null)
  * }}
  */
-var Row;
+let Row;
 
 /**
  * @typedef {{
@@ -63,7 +66,7 @@ var Row;
  *    query: ParsedQuery,
  * }}
  */
-var ResultsTable;
+let ResultsTable;
 
 /**
  * @typedef {{
@@ -80,4 +83,4 @@ var ResultsTable;
  *     ty: number,
  * }}
  */
-var Results;
+let Results;
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index 90592335d5ddf..9e5de9a843ab1 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -1,3 +1,6 @@
+/* eslint-env es6 */
+/* eslint no-var: "error" */
+/* eslint prefer-const: "error" */
 // Local js definitions:
 /* global addClass, getSettingValue, hasClass, searchState */
 /* global onEach, onEachLazy, removeClass */
@@ -11,7 +14,7 @@ if (!String.prototype.startsWith) {
 }
 if (!String.prototype.endsWith) {
     String.prototype.endsWith = function(suffix, length) {
-        var l = length || this.length;
+        const l = length || this.length;
         return this.indexOf(suffix, l - suffix.length) !== -1;
     };
 }
@@ -40,7 +43,7 @@ if (!DOMTokenList.prototype.remove) {
 // Get a value from the rustdoc-vars div, which is used to convey data from
 // Rust to the JS. If there is no such element, return null.
 function getVar(name) {
-    var el = document.getElementById("rustdoc-vars");
+    const el = document.getElementById("rustdoc-vars");
     if (el) {
         return el.attributes["data-" + name].value;
     } else {
@@ -59,7 +62,7 @@ function resourcePath(basename, extension) {
     window.currentCrate = getVar("current-crate");
     window.searchJS =  resourcePath("search", ".js");
     window.searchIndexJS = resourcePath("search-index", ".js");
-    var sidebarVars = document.getElementById("sidebar-vars");
+    const sidebarVars = document.getElementById("sidebar-vars");
     if (sidebarVars) {
         window.sidebarCurrent = {
             name: sidebarVars.attributes["data-name"].value,
@@ -68,8 +71,8 @@ function resourcePath(basename, extension) {
         };
         // FIXME: It would be nicer to generate this text content directly in HTML,
         // but with the current code it's hard to get the right information in the right place.
-        var mobileLocationTitle = document.querySelector(".mobile-topbar h2.location");
-        var locationTitle = document.querySelector(".sidebar h2.location");
+        const mobileLocationTitle = document.querySelector(".mobile-topbar h2.location");
+        const locationTitle = document.querySelector(".sidebar h2.location");
         if (mobileLocationTitle && locationTitle) {
             mobileLocationTitle.innerHTML = locationTitle.innerHTML;
         }
@@ -91,16 +94,16 @@ function getVirtualKey(ev) {
         return ev.key;
     }
 
-    var c = ev.charCode || ev.keyCode;
+    const c = ev.charCode || ev.keyCode;
     if (c == 27) {
         return "Escape";
     }
     return String.fromCharCode(c);
 }
 
-var THEME_PICKER_ELEMENT_ID = "theme-picker";
-var THEMES_ELEMENT_ID = "theme-choices";
-var MAIN_ID = "main-content";
+const THEME_PICKER_ELEMENT_ID = "theme-picker";
+const THEMES_ELEMENT_ID = "theme-choices";
+const MAIN_ID = "main-content";
 
 function getThemesElement() {
     return document.getElementById(THEMES_ELEMENT_ID);
@@ -116,8 +119,8 @@ function getNakedUrl() {
 }
 
 function showThemeButtonState() {
-    var themePicker = getThemePickerElement();
-    var themeChoices = getThemesElement();
+    const themePicker = getThemePickerElement();
+    const themeChoices = getThemesElement();
 
     themeChoices.style.display = "block";
     themePicker.style.borderBottomRightRadius = "0";
@@ -125,8 +128,8 @@ function showThemeButtonState() {
 }
 
 function hideThemeButtonState() {
-    var themePicker = getThemePickerElement();
-    var themeChoices = getThemesElement();
+    const themePicker = getThemePickerElement();
+    const themeChoices = getThemesElement();
 
     themeChoices.style.display = "none";
     themePicker.style.borderBottomRightRadius = "3px";
@@ -138,9 +141,9 @@ function hideThemeButtonState() {
     if (!document.location.href.startsWith("file:///")) {
         return;
     }
-    var themeChoices = getThemesElement();
-    var themePicker = getThemePickerElement();
-    var availableThemes = getVar("themes").split(",");
+    const themeChoices = getThemesElement();
+    const themePicker = getThemePickerElement();
+    const availableThemes = getVar("themes").split(",");
 
     removeClass(themeChoices.parentElement, "hidden");
 
@@ -153,8 +156,8 @@ function hideThemeButtonState() {
     }
 
     function handleThemeButtonsBlur(e) {
-        var active = document.activeElement;
-        var related = e.relatedTarget;
+        const active = document.activeElement;
+        const related = e.relatedTarget;
 
         if (active.id !== THEME_PICKER_ELEMENT_ID &&
             (!active.parentNode || active.parentNode.id !== THEMES_ELEMENT_ID) &&
@@ -168,7 +171,7 @@ function hideThemeButtonState() {
     themePicker.onclick = switchThemeButtonState;
     themePicker.onblur = handleThemeButtonsBlur;
     availableThemes.forEach(function(item) {
-        var but = document.createElement("button");
+        const but = document.createElement("button");
         but.textContent = item;
         but.onclick = function() {
             switchTheme(window.currentTheme, window.mainTheme, item, true);
@@ -236,10 +239,10 @@ function hideThemeButtonState() {
             }
         },
         getQueryStringParams: function() {
-            var params = {};
+            const params = {};
             window.location.search.substring(1).split("&").
                 map(function(s) {
-                    var pair = s.split("=");
+                    const pair = s.split("=");
                     params[decodeURIComponent(pair[0])] =
                         typeof pair[1] === "undefined" ? null : decodeURIComponent(pair[1]);
                 });
@@ -249,17 +252,17 @@ function hideThemeButtonState() {
             return window.history && typeof window.history.pushState === "function";
         },
         setup: function() {
-            var search_input = searchState.input;
+            const search_input = searchState.input;
             if (!searchState.input) {
                 return;
             }
             function loadScript(url) {
-                var script = document.createElement('script');
+                const script = document.createElement('script');
                 script.src = url;
                 document.head.append(script);
             }
 
-            var searchLoaded = false;
+            let searchLoaded = false;
             function loadSearch() {
                 if (!searchLoaded) {
                     searchLoaded = true;
@@ -278,9 +281,9 @@ function hideThemeButtonState() {
                 loadSearch();
             }
 
-            var params = searchState.getQueryStringParams();
+            const params = searchState.getQueryStringParams();
             if (params.search !== undefined) {
-                var search = searchState.outputElement();
+                const search = searchState.outputElement();
                 search.innerHTML = "<h3 class=\"search-loading\">" +
                     searchState.loadingText + "</h3>";
                 searchState.showResults(search);
@@ -291,7 +294,7 @@ function hideThemeButtonState() {
 
     function getPageId() {
         if (window.location.hash) {
-            var tmp = window.location.hash.replace(/^#/, "");
+            const tmp = window.location.hash.replace(/^#/, "");
             if (tmp.length > 0) {
                 return tmp;
             }
@@ -299,18 +302,18 @@ function hideThemeButtonState() {
         return null;
     }
 
-    var toggleAllDocsId = "toggle-all-docs";
-    var main = document.getElementById(MAIN_ID);
-    var savedHash = "";
+    const toggleAllDocsId = "toggle-all-docs";
+    const main = document.getElementById(MAIN_ID);
+    let savedHash = "";
 
     function handleHashes(ev) {
-        var elem;
-        var search = searchState.outputElement();
+        let elem;
+        const search = searchState.outputElement();
         if (ev !== null && search && !hasClass(search, "hidden") && ev.newURL) {
             // This block occurs when clicking on an element in the navbar while
             // in a search.
             searchState.hideResults(search);
-            var hash = ev.newURL.slice(ev.newURL.indexOf("#") + 1);
+            const hash = ev.newURL.slice(ev.newURL.indexOf("#") + 1);
             if (searchState.browserSupportsHistoryApi()) {
                 // `window.location.search`` contains all the query parameters, not just `search`.
                 history.replaceState(null, "",
@@ -333,7 +336,7 @@ function hideThemeButtonState() {
 
     function onHashChange(ev) {
         // If we're in mobile mode, we should hide the sidebar in any case.
-        var sidebar = document.getElementsByClassName("sidebar")[0];
+        const sidebar = document.getElementsByClassName("sidebar")[0];
         removeClass(sidebar, "shown");
         handleHashes(ev);
     }
@@ -386,8 +389,8 @@ function hideThemeButtonState() {
     }
 
     function handleEscape(ev) {
-        var help = getHelpElement(false);
-        var search = searchState.outputElement();
+        const help = getHelpElement(false);
+        const search = searchState.outputElement();
         if (help && !hasClass(help, "hidden")) {
             displayHelp(false, ev, help);
         } else if (search && !hasClass(search, "hidden")) {
@@ -399,13 +402,15 @@ function hideThemeButtonState() {
         hideThemeButtonState();
     }
 
-    var disableShortcuts = getSettingValue("disable-shortcuts") === "true";
+    const disableShortcuts = getSettingValue("disable-shortcuts") === "true";
     function handleShortcut(ev) {
         // Don't interfere with browser shortcuts
         if (ev.ctrlKey || ev.altKey || ev.metaKey || disableShortcuts) {
             return;
         }
 
+        let themePicker;
+
         if (document.activeElement.tagName === "INPUT") {
             switch (getVirtualKey(ev)) {
             case "Escape":
@@ -439,7 +444,7 @@ function hideThemeButtonState() {
             case "T":
                 displayHelp(false, ev);
                 ev.preventDefault();
-                var themePicker = getThemePickerElement();
+                themePicker = getThemePickerElement();
                 themePicker.click();
                 themePicker.focus();
                 break;
@@ -453,8 +458,8 @@ function hideThemeButtonState() {
     }
 
     function handleThemeKeyDown(ev) {
-        var active = document.activeElement;
-        var themes = getThemesElement();
+        const active = document.activeElement;
+        const themes = getThemesElement();
         switch (getVirtualKey(ev)) {
         case "ArrowUp":
             ev.preventDefault();
@@ -499,36 +504,11 @@ function hideThemeButtonState() {
     document.addEventListener("keypress", handleShortcut);
     document.addEventListener("keydown", handleShortcut);
 
-    (function() {
-        var x = document.getElementsByClassName("version-selector");
-        if (x.length > 0) {
-            x[0].onchange = function() {
-                var i, match,
-                    url = document.location.href,
-                    stripped = "",
-                    len = window.rootPath.match(/\.\.\//g).length + 1;
-
-                for (i = 0; i < len; ++i) {
-                    match = url.match(/\/[^/]*$/);
-                    if (i < len - 1) {
-                        stripped = match[0] + stripped;
-                    }
-                    url = url.substring(0, url.length - match[0].length);
-                }
-
-                var selectedVersion = document.getElementsByClassName("version-selector")[0].value;
-                url += "/" + selectedVersion + stripped;
-
-                document.location.href = url;
-            };
-        }
-    }());
-
     // delayed sidebar rendering.
     window.initSidebarItems = function(items) {
-        var sidebar = document.getElementsByClassName("sidebar-elems")[0];
-        var others;
-        var current = window.sidebarCurrent;
+        const sidebar = document.getElementsByClassName("sidebar-elems")[0];
+        let others;
+        const current = window.sidebarCurrent;
 
         function addSidebarCrates(crates) {
             if (!hasClass(document.body, "crate")) {
@@ -536,23 +516,23 @@ function hideThemeButtonState() {
                 return;
             }
             // Draw a convenient sidebar of known crates if we have a listing
-            var div = document.createElement("div");
+            const div = document.createElement("div");
             div.className = "block crate";
             div.innerHTML = "<h3>Crates</h3>";
-            var ul = document.createElement("ul");
+            const ul = document.createElement("ul");
             div.appendChild(ul);
 
-            for (var i = 0; i < crates.length; ++i) {
-                var klass = "crate";
-                if (window.rootPath !== "./" && crates[i] === window.currentCrate) {
+            for (const crate of crates) {
+                let klass = "crate";
+                if (window.rootPath !== "./" && crate === window.currentCrate) {
                     klass += " current";
                 }
-                var link = document.createElement("a");
-                link.href = window.rootPath + crates[i] + "/index.html";
+                const link = document.createElement("a");
+                link.href = window.rootPath + crate + "/index.html";
                 link.className = klass;
-                link.textContent = crates[i];
+                link.textContent = crate;
 
-                var li = document.createElement("li");
+                const li = document.createElement("li");
                 li.appendChild(link);
                 ul.appendChild(li);
             }
@@ -568,39 +548,38 @@ function hideThemeButtonState() {
          *                          "Modules", or "Macros".
          */
         function block(shortty, id, longty) {
-            var filtered = items[shortty];
+            const filtered = items[shortty];
             if (!filtered) {
                 return;
             }
 
-            var div = document.createElement("div");
+            const div = document.createElement("div");
             div.className = "block " + shortty;
-            var h3 = document.createElement("h3");
+            const h3 = document.createElement("h3");
             h3.innerHTML = `<a href="index.html#${id}">${longty}</a>`;
             div.appendChild(h3);
-            var ul = document.createElement("ul");
+            const ul = document.createElement("ul");
 
-            for (var i = 0, len = filtered.length; i < len; ++i) {
-                var item = filtered[i];
-                var name = item[0];
-                var desc = item[1]; // can be null
+            for (const item of filtered) {
+                const name = item[0];
+                const desc = item[1]; // can be null
 
-                var klass = shortty;
+                let klass = shortty;
                 if (name === current.name && shortty === current.ty) {
                     klass += " current";
                 }
-                var path;
+                let path;
                 if (shortty === "mod") {
                     path = name + "/index.html";
                 } else {
                     path = shortty + "." + name + ".html";
                 }
-                var link = document.createElement("a");
+                const link = document.createElement("a");
                 link.href = current.relpath + path;
                 link.title = desc;
                 link.className = klass;
                 link.textContent = name;
-                var li = document.createElement("li");
+                const li = document.createElement("li");
                 li.appendChild(link);
                 ul.appendChild(li);
             }
@@ -613,7 +592,7 @@ function hideThemeButtonState() {
             others.className = "others";
             sidebar.appendChild(others);
 
-            var isModule = hasClass(document.body, "mod");
+            const isModule = hasClass(document.body, "mod");
             if (!isModule) {
                 block("primitive", "primitives", "Primitive Types");
                 block("mod", "modules", "Modules");
@@ -638,8 +617,9 @@ function hideThemeButtonState() {
     };
 
     window.register_implementors = function(imp) {
-        var implementors = document.getElementById("implementors-list");
-        var synthetic_implementors = document.getElementById("synthetic-implementors-list");
+        const implementors = document.getElementById("implementors-list");
+        const synthetic_implementors = document.getElementById("synthetic-implementors-list");
+        const inlined_types = new Set();
 
         if (synthetic_implementors) {
             // This `inlined_types` variable is used to avoid having the same implementation
@@ -647,9 +627,8 @@ function hideThemeButtonState() {
             //
             // By the way, this is only used by and useful for traits implemented automatically
             // (like "Send" and "Sync").
-            var inlined_types = new Set();
             onEachLazy(synthetic_implementors.getElementsByClassName("impl"), function(el) {
-                var aliases = el.getAttribute("data-aliases");
+                const aliases = el.getAttribute("data-aliases");
                 if (!aliases) {
                     return;
                 }
@@ -659,48 +638,48 @@ function hideThemeButtonState() {
             });
         }
 
-        var currentNbImpls = implementors.getElementsByClassName("impl").length;
-        var traitName = document.querySelector("h1.fqn > .in-band > .trait").textContent;
-        var baseIdName = "impl-" + traitName + "-";
-        var libs = Object.getOwnPropertyNames(imp);
-        for (var i = 0, llength = libs.length; i < llength; ++i) {
-            if (libs[i] === window.currentCrate) { continue; }
-            var structs = imp[libs[i]];
+        let currentNbImpls = implementors.getElementsByClassName("impl").length;
+        const traitName = document.querySelector("h1.fqn > .in-band > .trait").textContent;
+        const baseIdName = "impl-" + traitName + "-";
+        const libs = Object.getOwnPropertyNames(imp);
+        for (const lib of libs) {
+            if (lib === window.currentCrate) {
+                continue;
+            }
+            const structs = imp[lib];
 
             struct_loop:
-            for (var j = 0, slength = structs.length; j < slength; ++j) {
-                var struct = structs[j];
-
-                var list = struct.synthetic ? synthetic_implementors : implementors;
+            for (const struct of structs) {
+                const list = struct.synthetic ? synthetic_implementors : implementors;
 
                 if (struct.synthetic) {
-                    for (var k = 0, stlength = struct.types.length; k < stlength; k++) {
-                        if (inlined_types.has(struct.types[k])) {
+                    for (const struct_type of struct.types) {
+                        if (inlined_types.has(struct_type)) {
                             continue struct_loop;
                         }
-                        inlined_types.add(struct.types[k]);
+                        inlined_types.add(struct_type);
                     }
                 }
 
-                var code = document.createElement("h3");
+                const code = document.createElement("h3");
                 code.innerHTML = struct.text;
                 addClass(code, "code-header");
                 addClass(code, "in-band");
 
                 onEachLazy(code.getElementsByTagName("a"), function(elem) {
-                    var href = elem.getAttribute("href");
+                    const href = elem.getAttribute("href");
 
                     if (href && href.indexOf("http") !== 0) {
                         elem.setAttribute("href", window.rootPath + href);
                     }
                 });
 
-                var currentId = baseIdName + currentNbImpls;
-                var anchor = document.createElement("a");
+                const currentId = baseIdName + currentNbImpls;
+                const anchor = document.createElement("a");
                 anchor.href = "#" + currentId;
                 addClass(anchor, "anchor");
 
-                var display = document.createElement("div");
+                const display = document.createElement("div");
                 display.id = currentId;
                 addClass(display, "impl");
                 display.appendChild(anchor);
@@ -725,11 +704,11 @@ function hideThemeButtonState() {
     }
 
     function toggleAllDocs() {
-        var innerToggle = document.getElementById(toggleAllDocsId);
+        const innerToggle = document.getElementById(toggleAllDocsId);
         if (!innerToggle) {
             return;
         }
-        var sectionIsCollapsed = false;
+        let sectionIsCollapsed = false;
         if (hasClass(innerToggle, "will-expand")) {
             removeClass(innerToggle, "will-expand");
             onEachLazy(document.getElementsByClassName("rustdoc-toggle"), function(e) {
@@ -759,17 +738,17 @@ function hideThemeButtonState() {
     }
 
     (function() {
-        var toggles = document.getElementById(toggleAllDocsId);
+        const toggles = document.getElementById(toggleAllDocsId);
         if (toggles) {
             toggles.onclick = toggleAllDocs;
         }
 
-        var hideMethodDocs = getSettingValue("auto-hide-method-docs") === "true";
-        var hideImplementations = getSettingValue("auto-hide-trait-implementations") === "true";
-        var hideLargeItemContents = getSettingValue("auto-hide-large-items") !== "false";
+        const hideMethodDocs = getSettingValue("auto-hide-method-docs") === "true";
+        const hideImplementations = getSettingValue("auto-hide-trait-implementations") === "true";
+        const hideLargeItemContents = getSettingValue("auto-hide-large-items") !== "false";
 
         function setImplementorsTogglesOpen(id, open) {
-            var list = document.getElementById(id);
+            const list = document.getElementById(id);
             if (list !== null) {
                 onEachLazy(list.getElementsByClassName("implementors-toggle"), function(e) {
                     e.open = open;
@@ -792,7 +771,7 @@ function hideThemeButtonState() {
 
         });
 
-        var pageId = getPageId();
+        const pageId = getPageId();
         if (pageId !== null) {
             expandSection(pageId);
         }
@@ -800,15 +779,15 @@ function hideThemeButtonState() {
 
     (function() {
         // To avoid checking on "rustdoc-line-numbers" value on every loop...
-        var lineNumbersFunc = function() {};
+        let lineNumbersFunc = function() {};
         if (getSettingValue("line-numbers") === "true") {
             lineNumbersFunc = function(x) {
-                var count = x.textContent.split("\n").length;
-                var elems = [];
-                for (var i = 0; i < count; ++i) {
+                const count = x.textContent.split("\n").length;
+                const elems = [];
+                for (let i = 0; i < count; ++i) {
                     elems.push(i + 1);
                 }
-                var node = document.createElement("pre");
+                const node = document.createElement("pre");
                 addClass(node, "line-number");
                 node.innerHTML = elems.join("\n");
                 x.parentNode.insertBefore(node, x);
@@ -835,12 +814,12 @@ function hideThemeButtonState() {
     }());
 
     function hideSidebar() {
-        var sidebar = document.getElementsByClassName("sidebar")[0];
+        const sidebar = document.getElementsByClassName("sidebar")[0];
         removeClass(sidebar, "shown");
     }
 
     function handleClick(id, f) {
-        var elem = document.getElementById(id);
+        const elem = document.getElementById(id);
         if (elem) {
             elem.addEventListener("click", f);
         }
@@ -879,10 +858,10 @@ function hideThemeButtonState() {
         };
     });
 
-    var sidebar_menu_toggle = document.getElementsByClassName("sidebar-menu-toggle")[0];
+    const sidebar_menu_toggle = document.getElementsByClassName("sidebar-menu-toggle")[0];
     if (sidebar_menu_toggle) {
         sidebar_menu_toggle.addEventListener("click", function() {
-            var sidebar = document.getElementsByClassName("sidebar")[0];
+            const sidebar = document.getElementsByClassName("sidebar")[0];
             if (!hasClass(sidebar, "shown")) {
                 addClass(sidebar, "shown");
             } else {
@@ -891,8 +870,8 @@ function hideThemeButtonState() {
         });
     }
 
-    var buildHelperPopup = function() {
-        var popup = document.createElement("aside");
+    let buildHelperPopup = function() {
+        const popup = document.createElement("aside");
         addClass(popup, "hidden");
         popup.id = "help";
 
@@ -903,13 +882,13 @@ function hideThemeButtonState() {
             }
         });
 
-        var book_info = document.createElement("span");
+        const book_info = document.createElement("span");
         book_info.className = "top";
         book_info.innerHTML = "You can find more information in \
             <a href=\"https://doc.rust-lang.org/rustdoc/\">the rustdoc book</a>.";
 
-        var container = document.createElement("div");
-        var shortcuts = [
+        const container = document.createElement("div");
+        const shortcuts = [
             ["?", "Show this help dialog"],
             ["S", "Focus the search field"],
             ["T", "Focus the theme picker menu"],
@@ -927,11 +906,11 @@ function hideThemeButtonState() {
                     })
                     .join("") + "</dt><dd>" + x[1] + "</dd>";
         }).join("");
-        var div_shortcuts = document.createElement("div");
+        const div_shortcuts = document.createElement("div");
         addClass(div_shortcuts, "shortcuts");
         div_shortcuts.innerHTML = "<h2>Keyboard Shortcuts</h2><dl>" + shortcuts + "</dl></div>";
 
-        var infos = [
+        const infos = [
             "Prefix searches with a type followed by a colon (e.g., <code>fn:</code>) to \
              restrict the search to a given item kind.",
             "Accepted kinds are: <code>fn</code>, <code>mod</code>, <code>struct</code>, \
@@ -947,7 +926,7 @@ function hideThemeButtonState() {
         ].map(function(x) {
             return "<p>" + x + "</p>";
         }).join("");
-        var div_infos = document.createElement("div");
+        const div_infos = document.createElement("div");
         addClass(div_infos, "infos");
         div_infos.innerHTML = "<h2>Search Tricks</h2>" + infos;
 
@@ -955,9 +934,9 @@ function hideThemeButtonState() {
         container.appendChild(div_shortcuts);
         container.appendChild(div_infos);
 
-        var rustdoc_version = document.createElement("span");
+        const rustdoc_version = document.createElement("span");
         rustdoc_version.className = "bottom";
-        var rustdoc_version_code = document.createElement("code");
+        const rustdoc_version_code = document.createElement("code");
         rustdoc_version_code.innerText = "rustdoc " + getVar("rustdoc-version");
         rustdoc_version.appendChild(rustdoc_version_code);
 
@@ -975,11 +954,11 @@ function hideThemeButtonState() {
 }());
 
 (function () {
-    var reset_button_timeout = null;
+    let reset_button_timeout = null;
 
     window.copy_path = function(but) {
-        var parent = but.parentElement;
-        var path = [];
+        const parent = but.parentElement;
+        const path = [];
 
         onEach(parent.childNodes, function(child) {
             if (child.tagName === 'A') {
@@ -987,7 +966,7 @@ function hideThemeButtonState() {
             }
         });
 
-        var el = document.createElement('textarea');
+        const el = document.createElement('textarea');
         el.value = path.join('::');
         el.setAttribute('readonly', '');
         // To not make it appear on the screen.
@@ -1002,7 +981,7 @@ function hideThemeButtonState() {
         // There is always one children, but multiple childNodes.
         but.children[0].style.display = 'none';
 
-        var tmp;
+        let tmp;
         if (but.childNodes.length < 2) {
             tmp = document.createTextNode('✓');
             but.appendChild(tmp);
diff --git a/src/librustdoc/html/static/js/scrape-examples.js b/src/librustdoc/html/static/js/scrape-examples.js
index a28fb46172990..865ed7190f36e 100644
--- a/src/librustdoc/html/static/js/scrape-examples.js
+++ b/src/librustdoc/html/static/js/scrape-examples.js
@@ -1,4 +1,7 @@
-/* global addClass, hasClass, removeClass, onEach */
+/* eslint-env es6 */
+/* eslint no-var: "error" */
+/* eslint prefer-const: "error" */
+/* global addClass, hasClass, removeClass, onEachLazy */
 
 (function () {
     // Number of lines shown when code viewer is not expanded
@@ -6,19 +9,19 @@
 
     // Scroll code block to the given code location
     function scrollToLoc(elt, loc) {
-        var lines = elt.querySelector('.line-numbers');
-        var scrollOffset;
+        const lines = elt.querySelector('.line-numbers');
+        let scrollOffset;
 
         // If the block is greater than the size of the viewer,
         // then scroll to the top of the block. Otherwise scroll
         // to the middle of the block.
         if (loc[1] - loc[0] > MAX_LINES) {
-            var line = Math.max(0, loc[0] - 1);
+            const line = Math.max(0, loc[0] - 1);
             scrollOffset = lines.children[line].offsetTop;
         } else {
-            var wrapper = elt.querySelector(".code-wrapper");
-            var halfHeight = wrapper.offsetHeight / 2;
-            var offsetMid = (lines.children[loc[0]].offsetTop
+            const wrapper = elt.querySelector(".code-wrapper");
+            const halfHeight = wrapper.offsetHeight / 2;
+            const offsetMid = (lines.children[loc[0]].offsetTop
                              + lines.children[loc[1]].offsetTop) / 2;
             scrollOffset = offsetMid - halfHeight;
         }
@@ -28,21 +31,21 @@
     }
 
     function updateScrapedExample(example) {
-        var locs = JSON.parse(example.attributes.getNamedItem("data-locs").textContent);
-        var locIndex = 0;
-        var highlights = example.querySelectorAll('.highlight');
-        var link = example.querySelector('.scraped-example-title a');
+        const locs = JSON.parse(example.attributes.getNamedItem("data-locs").textContent);
+        let locIndex = 0;
+        const highlights = Array.prototype.slice.call(example.querySelectorAll('.highlight'));
+        const link = example.querySelector('.scraped-example-title a');
 
         if (locs.length > 1) {
             // Toggle through list of examples in a given file
-            var onChangeLoc = function(changeIndex) {
+            const onChangeLoc = function(changeIndex) {
                 removeClass(highlights[locIndex], 'focus');
                 changeIndex();
                 scrollToLoc(example, locs[locIndex][0]);
                 addClass(highlights[locIndex], 'focus');
 
-                var url = locs[locIndex][1];
-                var title = locs[locIndex][2];
+                const url = locs[locIndex][1];
+                const title = locs[locIndex][2];
 
                 link.href = url;
                 link.innerHTML = title;
@@ -63,7 +66,7 @@
                 });
         }
 
-        var expandButton = example.querySelector('.expand');
+        const expandButton = example.querySelector('.expand');
         if (expandButton) {
             expandButton.addEventListener('click', function () {
                 if (hasClass(example, "expanded")) {
@@ -79,24 +82,24 @@
         scrollToLoc(example, locs[0][0]);
     }
 
-    var firstExamples = document.querySelectorAll('.scraped-example-list > .scraped-example');
-    onEach(firstExamples, updateScrapedExample);
-    onEach(document.querySelectorAll('.more-examples-toggle'), function(toggle) {
+    const firstExamples = document.querySelectorAll('.scraped-example-list > .scraped-example');
+    onEachLazy(firstExamples, updateScrapedExample);
+    onEachLazy(document.querySelectorAll('.more-examples-toggle'), function(toggle) {
         // Allow users to click the left border of the <details> section to close it,
         // since the section can be large and finding the [+] button is annoying.
-        toggle.querySelectorAll('.toggle-line, .hide-more').forEach(button => {
+        onEachLazy(toggle.querySelectorAll('.toggle-line, .hide-more'), button => {
             button.addEventListener('click', function() {
                 toggle.open = false;
             });
         });
 
-        var moreExamples = toggle.querySelectorAll('.scraped-example');
+        const moreExamples = toggle.querySelectorAll('.scraped-example');
         toggle.querySelector('summary').addEventListener('click', function() {
             // Wrapping in setTimeout ensures the update happens after the elements are actually
             // visible. This is necessary since updateScrapedExample calls scrollToLoc which
             // depends on offsetHeight, a property that requires an element to be visible to
             // compute correctly.
-            setTimeout(function() { onEach(moreExamples, updateScrapedExample); });
+            setTimeout(function() { onEachLazy(moreExamples, updateScrapedExample); });
         }, {once: true});
     });
 })();
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index c1d2ec540b0b0..a6f7dd74af6b0 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -112,10 +112,6 @@ window.initSearch = function(rawSearchIndex) {
      *  @type {Array<Row>}
      */
     let searchIndex;
-    /**
-     *  @type {Array<string>}
-     */
-    let searchWords = [];
     let currentResults;
     const ALIASES = {};
     const params = searchState.getQueryStringParams();
@@ -2129,7 +2125,10 @@ window.initSearch = function(rawSearchIndex) {
         search(undefined, true);
     }
 
-    searchWords = buildIndex(rawSearchIndex);
+    /**
+     *  @type {Array<string>}
+     */
+    const searchWords = buildIndex(rawSearchIndex);
     registerSearchEvents();
 
     function runSearchIfNeeded() {
diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js
index 549d56450d803..7bc6f6cfe043d 100644
--- a/src/librustdoc/html/static/js/settings.js
+++ b/src/librustdoc/html/static/js/settings.js
@@ -1,7 +1,7 @@
-// Local js definitions:
 /* eslint-env es6 */
 /* eslint no-var: "error" */
 /* eslint prefer-const: "error" */
+// Local js definitions:
 /* global getSettingValue, getVirtualKey, onEachLazy, updateLocalStorage, updateSystemTheme */
 /* global addClass, removeClass */
 
diff --git a/src/librustdoc/html/static/js/source-script.js b/src/librustdoc/html/static/js/source-script.js
index aa77e62ba5acb..c48a847665ef5 100644
--- a/src/librustdoc/html/static/js/source-script.js
+++ b/src/librustdoc/html/static/js/source-script.js
@@ -1,3 +1,7 @@
+/* eslint-env es6 */
+/* eslint no-var: "error" */
+/* eslint prefer-const: "error" */
+
 // From rust:
 /* global search, sourcesIndex */
 
@@ -7,15 +11,15 @@
 (function() {
 
 function getCurrentFilePath() {
-    var parts = window.location.pathname.split("/");
-    var rootPathParts = window.rootPath.split("/");
+    const parts = window.location.pathname.split("/");
+    const rootPathParts = window.rootPath.split("/");
 
-    for (var i = 0, len = rootPathParts.length; i < len; ++i) {
-        if (rootPathParts[i] === "..") {
+    for (const rootPathPart of rootPathParts) {
+        if (rootPathPart === "..") {
             parts.pop();
         }
     }
-    var file = window.location.pathname.substring(parts.join("/").length);
+    let file = window.location.pathname.substring(parts.join("/").length);
     if (file.startsWith("/")) {
         file = file.substring(1);
     }
@@ -23,7 +27,7 @@ function getCurrentFilePath() {
 }
 
 function createDirEntry(elem, parent, fullPath, currentFile, hasFoundFile) {
-    var name = document.createElement("div");
+    const name = document.createElement("div");
     name.className = "name";
 
     fullPath += elem["name"] + "/";
@@ -37,16 +41,13 @@ function createDirEntry(elem, parent, fullPath, currentFile, hasFoundFile) {
     };
     name.innerText = elem["name"];
 
-    var i, len;
-
-    var children = document.createElement("div");
+    const children = document.createElement("div");
     children.className = "children";
-    var folders = document.createElement("div");
+    const folders = document.createElement("div");
     folders.className = "folders";
     if (elem.dirs) {
-        for (i = 0, len = elem.dirs.length; i < len; ++i) {
-            if (createDirEntry(elem.dirs[i], folders, fullPath, currentFile,
-                               hasFoundFile)) {
+        for (const dir of elem.dirs) {
+            if (createDirEntry(dir, folders, fullPath, currentFile, hasFoundFile)) {
                 addClass(name, "expand");
                 hasFoundFile = true;
             }
@@ -54,14 +55,14 @@ function createDirEntry(elem, parent, fullPath, currentFile, hasFoundFile) {
     }
     children.appendChild(folders);
 
-    var files = document.createElement("div");
+    const files = document.createElement("div");
     files.className = "files";
     if (elem.files) {
-        for (i = 0, len = elem.files.length; i < len; ++i) {
-            var file = document.createElement("a");
-            file.innerText = elem.files[i];
-            file.href = window.rootPath + "src/" + fullPath + elem.files[i] + ".html";
-            if (!hasFoundFile && currentFile === fullPath + elem.files[i]) {
+        for (const file_text of elem.files) {
+            const file = document.createElement("a");
+            file.innerText = file_text;
+            file.href = window.rootPath + "src/" + fullPath + file_text + ".html";
+            if (!hasFoundFile && currentFile === fullPath + file_text) {
                 file.className = "selected";
                 addClass(name, "expand");
                 hasFoundFile = true;
@@ -77,8 +78,8 @@ function createDirEntry(elem, parent, fullPath, currentFile, hasFoundFile) {
 }
 
 function toggleSidebar() {
-    var sidebar = document.querySelector("nav.sidebar");
-    var child = this.children[0];
+    const sidebar = document.querySelector("nav.sidebar");
+    const child = this.children[0];
     if (child.innerText === ">") {
         sidebar.classList.add("expanded");
         child.innerText = "<";
@@ -91,11 +92,11 @@ function toggleSidebar() {
 }
 
 function createSidebarToggle() {
-    var sidebarToggle = document.createElement("div");
+    const sidebarToggle = document.createElement("div");
     sidebarToggle.id = "sidebar-toggle";
     sidebarToggle.onclick = toggleSidebar;
 
-    var inner = document.createElement("div");
+    const inner = document.createElement("div");
 
     if (getCurrentValue("source-sidebar-show") === "true") {
         inner.innerText = "<";
@@ -113,12 +114,12 @@ function createSourceSidebar() {
     if (!window.rootPath.endsWith("/")) {
         window.rootPath += "/";
     }
-    var container = document.querySelector("nav.sidebar");
+    const container = document.querySelector("nav.sidebar");
 
-    var sidebarToggle = createSidebarToggle();
+    const sidebarToggle = createSidebarToggle();
     container.insertBefore(sidebarToggle, container.firstChild);
 
-    var sidebar = document.createElement("div");
+    const sidebar = document.createElement("div");
     sidebar.id = "source-sidebar";
     if (getCurrentValue("source-sidebar-show") !== "true") {
         container.classList.remove("expanded");
@@ -126,10 +127,10 @@ function createSourceSidebar() {
         container.classList.add("expanded");
     }
 
-    var currentFile = getCurrentFilePath();
-    var hasFoundFile = false;
+    const currentFile = getCurrentFilePath();
+    let hasFoundFile = false;
 
-    var title = document.createElement("div");
+    const title = document.createElement("div");
     title.className = "title";
     title.innerText = "Files";
     sidebar.appendChild(title);
@@ -141,13 +142,13 @@ function createSourceSidebar() {
 
     container.appendChild(sidebar);
     // Focus on the current file in the source files sidebar.
-    var selected_elem = sidebar.getElementsByClassName("selected")[0];
+    const selected_elem = sidebar.getElementsByClassName("selected")[0];
     if (typeof selected_elem !== "undefined") {
         selected_elem.focus();
     }
 }
 
-var lineNumbersRegex = /^#?(\d+)(?:-(\d+))?$/;
+const lineNumbersRegex = /^#?(\d+)(?:-(\d+))?$/;
 
 function highlightSourceLines(match) {
     if (typeof match === "undefined") {
@@ -156,21 +157,21 @@ function highlightSourceLines(match) {
     if (!match) {
         return;
     }
-    var from = parseInt(match[1], 10);
-    var to = from;
+    let from = parseInt(match[1], 10);
+    let to = from;
     if (typeof match[2] !== "undefined") {
         to = parseInt(match[2], 10);
     }
     if (to < from) {
-        var tmp = to;
+        const tmp = to;
         to = from;
         from = tmp;
     }
-    var elem = document.getElementById(from);
+    let elem = document.getElementById(from);
     if (!elem) {
         return;
     }
-    var x = document.getElementById(from);
+    const x = document.getElementById(from);
     if (x) {
         x.scrollIntoView();
     }
@@ -179,7 +180,7 @@ function highlightSourceLines(match) {
             removeClass(i_e, "line-highlighted");
         });
     });
-    for (var i = from; i <= to; ++i) {
+    for (let i = from; i <= to; ++i) {
         elem = document.getElementById(i);
         if (!elem) {
             break;
@@ -188,11 +189,11 @@ function highlightSourceLines(match) {
     }
 }
 
-var handleSourceHighlight = (function() {
-    var prev_line_id = 0;
+const handleSourceHighlight = (function() {
+    let prev_line_id = 0;
 
-    var set_fragment = function(name) {
-        var x = window.scrollX,
+    const set_fragment = function(name) {
+        const x = window.scrollX,
             y = window.scrollY;
         if (searchState.browserSupportsHistoryApi()) {
             history.replaceState(null, null, "#" + name);
@@ -205,13 +206,13 @@ var handleSourceHighlight = (function() {
     };
 
     return function(ev) {
-        var cur_line_id = parseInt(ev.target.id, 10);
+        let cur_line_id = parseInt(ev.target.id, 10);
         ev.preventDefault();
 
         if (ev.shiftKey && prev_line_id) {
             // Swap selection if needed
             if (prev_line_id > cur_line_id) {
-                var tmp = prev_line_id;
+                const tmp = prev_line_id;
                 prev_line_id = cur_line_id;
                 cur_line_id = tmp;
             }
@@ -226,7 +227,7 @@ var handleSourceHighlight = (function() {
 }());
 
 window.addEventListener("hashchange", function() {
-    var match = window.location.hash.match(lineNumbersRegex);
+    const match = window.location.hash.match(lineNumbersRegex);
     if (match) {
         return highlightSourceLines(match);
     }
diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js
index ccf3d0a581a17..ae670ed989426 100644
--- a/src/librustdoc/html/static/js/storage.js
+++ b/src/librustdoc/html/static/js/storage.js
@@ -1,13 +1,17 @@
-var darkThemes = ["dark", "ayu"];
+/* eslint-env es6 */
+/* eslint no-var: "error" */
+/* eslint prefer-const: "error" */
+
+const darkThemes = ["dark", "ayu"];
 window.currentTheme = document.getElementById("themeStyle");
 window.mainTheme = document.getElementById("mainThemeStyle");
 
-var settingsDataset = (function () {
-    var settingsElement = document.getElementById("default-settings");
+const settingsDataset = (function () {
+    const settingsElement = document.getElementById("default-settings");
     if (settingsElement === null) {
         return null;
     }
-    var dataset = settingsElement.dataset;
+    const dataset = settingsElement.dataset;
     if (dataset === undefined) {
         return null;
     }
@@ -15,14 +19,14 @@ var settingsDataset = (function () {
 })();
 
 function getSettingValue(settingName) {
-    var current = getCurrentValue(settingName);
+    const current = getCurrentValue(settingName);
     if (current !== null) {
         return current;
     }
     if (settingsDataset !== null) {
         // See the comment for `default_settings.into_iter()` etc. in
         // `Options::from_matches` in `librustdoc/config.rs`.
-        var def = settingsDataset[settingName.replace(/-/g,'_')];
+        const def = settingsDataset[settingName.replace(/-/g,'_')];
         if (def !== undefined) {
             return def;
         }
@@ -30,9 +34,9 @@ function getSettingValue(settingName) {
     return null;
 }
 
-var localStoredTheme = getSettingValue("theme");
+const localStoredTheme = getSettingValue("theme");
 
-var savedHref = [];
+const savedHref = [];
 
 // eslint-disable-next-line no-unused-vars
 function hasClass(elem, className) {
@@ -63,17 +67,16 @@ function removeClass(elem, className) {
  */
 function onEach(arr, func, reversed) {
     if (arr && arr.length > 0 && func) {
-        var length = arr.length;
-        var i;
         if (reversed) {
-            for (i = length - 1; i >= 0; --i) {
+            const length = arr.length;
+            for (let i = length - 1; i >= 0; --i) {
                 if (func(arr[i])) {
                     return true;
                 }
             }
         } else {
-            for (i = 0; i < length; ++i) {
-                if (func(arr[i])) {
+            for (const elem of arr) {
+                if (func(elem)) {
                     return true;
                 }
             }
@@ -121,7 +124,7 @@ function getCurrentValue(name) {
 }
 
 function switchTheme(styleElem, mainStyleElem, newTheme, saveTheme) {
-    var newHref = mainStyleElem.href.replace(
+    const newHref = mainStyleElem.href.replace(
         /\/rustdoc([^/]*)\.css/, "/" + newTheme + "$1" + ".css");
 
     // If this new value comes from a system setting or from the previously
@@ -134,7 +137,7 @@ function switchTheme(styleElem, mainStyleElem, newTheme, saveTheme) {
         return;
     }
 
-    var found = false;
+    let found = false;
     if (savedHref.length === 0) {
         onEachLazy(document.getElementsByTagName("link"), function(el) {
             savedHref.push(el.href);
@@ -161,17 +164,17 @@ function useSystemTheme(value) {
     updateLocalStorage("use-system-theme", value);
 
     // update the toggle if we're on the settings page
-    var toggle = document.getElementById("use-system-theme");
+    const toggle = document.getElementById("use-system-theme");
     if (toggle && toggle instanceof HTMLInputElement) {
         toggle.checked = value;
     }
 }
 
-var updateSystemTheme = (function() {
+const updateSystemTheme = (function() {
     if (!window.matchMedia) {
         // fallback to the CSS computed value
         return function() {
-            var cssTheme = getComputedStyle(document.documentElement)
+            const cssTheme = getComputedStyle(document.documentElement)
                 .getPropertyValue('content');
 
             switchTheme(
@@ -184,16 +187,16 @@ var updateSystemTheme = (function() {
     }
 
     // only listen to (prefers-color-scheme: dark) because light is the default
-    var mql = window.matchMedia("(prefers-color-scheme: dark)");
+    const mql = window.matchMedia("(prefers-color-scheme: dark)");
 
     function handlePreferenceChange(mql) {
-        let use = function(theme) {
+        const use = function(theme) {
             switchTheme(window.currentTheme, window.mainTheme, theme, true);
         };
         // maybe the user has disabled the setting in the meantime!
         if (getSettingValue("use-system-theme") !== "false") {
-            var lightTheme = getSettingValue("preferred-light-theme") || "light";
-            var darkTheme = getSettingValue("preferred-dark-theme") || "dark";
+            const lightTheme = getSettingValue("preferred-light-theme") || "light";
+            const darkTheme = getSettingValue("preferred-dark-theme") || "dark";
 
             if (mql.matches) {
                 use(darkTheme);
diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs
index 6962b5c7ee302..9644e3d15fdfa 100644
--- a/src/librustdoc/passes/collect_trait_impls.rs
+++ b/src/librustdoc/passes/collect_trait_impls.rs
@@ -33,13 +33,42 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate
         coll.items
     };
 
-    let mut new_items = Vec::new();
+    let mut new_items_external = Vec::new();
+    let mut new_items_local = Vec::new();
 
     // External trait impls.
     cx.with_all_trait_impls(|cx, all_trait_impls| {
         let _prof_timer = cx.tcx.sess.prof.generic_activity("build_extern_trait_impls");
         for &impl_def_id in all_trait_impls.iter().skip_while(|def_id| def_id.is_local()) {
-            inline::build_impl(cx, None, impl_def_id, None, &mut new_items);
+            inline::build_impl(cx, None, impl_def_id, None, &mut new_items_external);
+        }
+    });
+
+    // Local trait impls.
+    cx.with_all_trait_impls(|cx, all_trait_impls| {
+        let _prof_timer = cx.tcx.sess.prof.generic_activity("build_local_trait_impls");
+        let mut attr_buf = Vec::new();
+        for &impl_def_id in all_trait_impls.iter().take_while(|def_id| def_id.is_local()) {
+            let mut parent = cx.tcx.parent(impl_def_id);
+            while let Some(did) = parent {
+                attr_buf.extend(
+                    cx.tcx
+                        .get_attrs(did)
+                        .iter()
+                        .filter(|attr| attr.has_name(sym::doc))
+                        .filter(|attr| {
+                            if let Some([attr]) = attr.meta_item_list().as_deref() {
+                                attr.has_name(sym::cfg)
+                            } else {
+                                false
+                            }
+                        })
+                        .cloned(),
+                );
+                parent = cx.tcx.parent(did);
+            }
+            inline::build_impl(cx, None, impl_def_id, Some(&attr_buf), &mut new_items_local);
+            attr_buf.clear();
         }
     });
 
@@ -47,7 +76,7 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate
         for def_id in PrimitiveType::all_impls(cx.tcx) {
             // Try to inline primitive impls from other crates.
             if !def_id.is_local() {
-                inline::build_impl(cx, None, def_id, None, &mut new_items);
+                inline::build_impl(cx, None, def_id, None, &mut new_items_external);
             }
         }
         for (prim, did) in PrimitiveType::primitive_locations(cx.tcx) {
@@ -57,7 +86,7 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate
             if did.is_local() {
                 for def_id in prim.impls(cx.tcx) {
                     let impls = get_auto_trait_and_blanket_impls(cx, def_id);
-                    new_items.extend(impls.filter(|i| cx.inlined.insert(i.item_id)));
+                    new_items_external.extend(impls.filter(|i| cx.inlined.insert(i.item_id)));
                 }
             }
         }
@@ -71,6 +100,7 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate
         cx: &DocContext<'_>,
         map: &FxHashMap<DefId, &Type>,
         cleaner: &mut BadImplStripper<'_>,
+        targets: &mut FxHashSet<DefId>,
         type_did: DefId,
     ) {
         if let Some(target) = map.get(&type_did) {
@@ -79,18 +109,18 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate
                 cleaner.prims.insert(target_prim);
             } else if let Some(target_did) = target.def_id(&cx.cache) {
                 // `impl Deref<Target = S> for S`
-                if target_did == type_did {
+                if !targets.insert(target_did) {
                     // Avoid infinite cycles
                     return;
                 }
                 cleaner.items.insert(target_did.into());
-                add_deref_target(cx, map, cleaner, target_did);
+                add_deref_target(cx, map, cleaner, targets, target_did);
             }
         }
     }
 
     // scan through included items ahead of time to splice in Deref targets to the "valid" sets
-    for it in &new_items {
+    for it in new_items_external.iter().chain(new_items_local.iter()) {
         if let ImplItem(Impl { ref for_, ref trait_, ref items, .. }) = *it.kind {
             if trait_.as_ref().map(|t| t.def_id()) == cx.tcx.lang_items().deref_trait()
                 && cleaner.keep_impl(for_, true)
@@ -114,7 +144,15 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate
                         // `Deref` target type and the impl for type positions, this map of types is keyed by
                         // `DefId` and for convenience uses a special cleaner that accepts `DefId`s directly.
                         if cleaner.keep_impl_with_def_id(for_did.into()) {
-                            add_deref_target(cx, &type_did_to_deref_target, &mut cleaner, for_did);
+                            let mut targets = FxHashSet::default();
+                            targets.insert(for_did);
+                            add_deref_target(
+                                cx,
+                                &type_did_to_deref_target,
+                                &mut cleaner,
+                                &mut targets,
+                                for_did,
+                            );
                         }
                     }
                 }
@@ -122,7 +160,8 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate
         }
     }
 
-    new_items.retain(|it| {
+    // Filter out external items that are not needed
+    new_items_external.retain(|it| {
         if let ImplItem(Impl { ref for_, ref trait_, ref kind, .. }) = *it.kind {
             cleaner.keep_impl(
                 for_,
@@ -134,37 +173,10 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate
         }
     });
 
-    // Local trait impls.
-    cx.with_all_trait_impls(|cx, all_trait_impls| {
-        let _prof_timer = cx.tcx.sess.prof.generic_activity("build_local_trait_impls");
-        let mut attr_buf = Vec::new();
-        for &impl_def_id in all_trait_impls.iter().take_while(|def_id| def_id.is_local()) {
-            let mut parent = cx.tcx.parent(impl_def_id);
-            while let Some(did) = parent {
-                attr_buf.extend(
-                    cx.tcx
-                        .get_attrs(did)
-                        .iter()
-                        .filter(|attr| attr.has_name(sym::doc))
-                        .filter(|attr| {
-                            if let Some([attr]) = attr.meta_item_list().as_deref() {
-                                attr.has_name(sym::cfg)
-                            } else {
-                                false
-                            }
-                        })
-                        .cloned(),
-                );
-                parent = cx.tcx.parent(did);
-            }
-            inline::build_impl(cx, None, impl_def_id, Some(&attr_buf), &mut new_items);
-            attr_buf.clear();
-        }
-    });
-
     if let ModuleItem(Module { items, .. }) = &mut *krate.module.kind {
         items.extend(synth_impls);
-        items.extend(new_items);
+        items.extend(new_items_external);
+        items.extend(new_items_local);
     } else {
         panic!("collect-trait-impls can't run");
     };
diff --git a/src/test/codegen/remap_path_prefix/main.rs b/src/test/codegen/remap_path_prefix/main.rs
index 698dfe6b4f341..b13d576295c60 100644
--- a/src/test/codegen/remap_path_prefix/main.rs
+++ b/src/test/codegen/remap_path_prefix/main.rs
@@ -22,7 +22,7 @@ fn main() {
 }
 
 // Here we check that local debuginfo is mapped correctly.
-// CHECK: !DIFile(filename: "/the/src/remap_path_prefix/main.rs", directory: "/the/cwd/"
+// CHECK: !DIFile(filename: "/the/src/remap_path_prefix/main.rs", directory: "/the/cwd"
 
 // And here that debuginfo from other crates are expanded to absolute paths.
 // CHECK: !DIFile(filename: "/the/aux-src/remap_path_prefix_aux.rs", directory: ""
diff --git a/src/test/rustdoc/deref-slice-core.rs b/src/test/rustdoc/deref-slice-core.rs
new file mode 100644
index 0000000000000..cccf273a82028
--- /dev/null
+++ b/src/test/rustdoc/deref-slice-core.rs
@@ -0,0 +1,22 @@
+// https://github.com/rust-lang/rust/issues/95325
+//
+// Show methods reachable from Deref of primitive.
+#![no_std]
+
+use core::ops::Deref;
+
+// @has 'deref_slice_core/struct.MyArray.html'
+// @has '-' '//*[@id="deref-methods-%5BT%5D"]' 'Methods from Deref<Target = [T]>'
+// @has '-' '//*[@class="impl-items"]//*[@id="method.len"]' 'pub fn len(&self)'
+
+pub struct MyArray<T> {
+    array: [T; 10],
+}
+
+impl<T> Deref for MyArray<T> {
+    type Target = [T];
+
+    fn deref(&self) -> &Self::Target {
+        &self.array
+    }
+}
diff --git a/src/test/ui/lifetimes/elided-lifetime-in-path-in-impl-Fn.rs b/src/test/ui/lifetimes/elided-lifetime-in-path-in-impl-Fn.rs
new file mode 100644
index 0000000000000..9c9965d8fb8b5
--- /dev/null
+++ b/src/test/ui/lifetimes/elided-lifetime-in-path-in-impl-Fn.rs
@@ -0,0 +1,19 @@
+// check-pass
+
+struct Foo<'a>(&'a ());
+
+fn with_fn() -> fn(Foo) {
+    |_| ()
+}
+
+fn with_impl_fn() -> impl Fn(Foo) {
+    |_| ()
+}
+
+fn with_where_fn<T>()
+where
+    T: Fn(Foo),
+{
+}
+
+fn main() {}