From ae93e6e3b8035fb5a0e131d97612fa6ea34cf6e8 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 25 Apr 2022 14:12:12 +0200 Subject: [PATCH 01/14] Small JS code improvements --- src/librustdoc/html/static/js/search.js | 9 ++++----- src/librustdoc/html/static/js/settings.js | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index c4e74ea0657..2010d865e3f 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} */ let searchIndex; - /** - * @type {Array} - */ - let searchWords = []; let currentResults; const ALIASES = {}; const params = searchState.getQueryStringParams(); @@ -2118,7 +2114,10 @@ window.initSearch = function(rawSearchIndex) { search(undefined, true); } - searchWords = buildIndex(rawSearchIndex); + /** + * @type {Array} + */ + 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 549d56450d8..7bc6f6cfe04 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 */ From cb8da88c83937a5fdb95697cac6be87567841955 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 25 Apr 2022 14:23:06 +0200 Subject: [PATCH 02/14] Migrate externs.js to ES6 --- src/librustdoc/html/static/js/externs.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/html/static/js/externs.js b/src/librustdoc/html/static/js/externs.js index 0fe0fdadbd2..de881dbd081 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, * }} */ -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; From 016334a3ade1a8726f0b9278b8d5564eb2727335 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 25 Apr 2022 14:23:17 +0200 Subject: [PATCH 03/14] Migrate main.js to ES6 --- src/librustdoc/html/static/js/main.js | 258 +++++++++++++------------- 1 file changed, 130 insertions(+), 128 deletions(-) diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 90592335d5d..cc9dc0adbca 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 = "

" + searchState.loadingText + "

"; 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(); @@ -500,23 +505,21 @@ function hideThemeButtonState() { document.addEventListener("keydown", handleShortcut); (function() { - var x = document.getElementsByClassName("version-selector"); + const 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; + let url = document.location.href, stripped = ""; + const len = window.rootPath.match(/\.\.\//g).length + 1; - for (i = 0; i < len; ++i) { - match = url.match(/\/[^/]*$/); + for (let i = 0; i < len; ++i) { + const 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; + const selectedVersion = document.getElementsByClassName("version-selector")[0].value; url += "/" + selectedVersion + stripped; document.location.href = url; @@ -526,9 +529,9 @@ function hideThemeButtonState() { // 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 +539,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 = "

Crates

"; - 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 +571,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 = `${longty}`; 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 +615,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 +640,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 +650,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 +661,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 +727,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 +761,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 +794,7 @@ function hideThemeButtonState() { }); - var pageId = getPageId(); + const pageId = getPageId(); if (pageId !== null) { expandSection(pageId); } @@ -800,15 +802,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 +837,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 +881,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 +893,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 +905,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 \ the rustdoc book."; - 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 +929,11 @@ function hideThemeButtonState() { }) .join("") + "
" + x[1] + "
"; }).join(""); - var div_shortcuts = document.createElement("div"); + const div_shortcuts = document.createElement("div"); addClass(div_shortcuts, "shortcuts"); div_shortcuts.innerHTML = "

Keyboard Shortcuts

" + shortcuts + "
"; - var infos = [ + const infos = [ "Prefix searches with a type followed by a colon (e.g., fn:) to \ restrict the search to a given item kind.", "Accepted kinds are: fn, mod, struct, \ @@ -947,7 +949,7 @@ function hideThemeButtonState() { ].map(function(x) { return "

" + x + "

"; }).join(""); - var div_infos = document.createElement("div"); + const div_infos = document.createElement("div"); addClass(div_infos, "infos"); div_infos.innerHTML = "

Search Tricks

" + infos; @@ -955,9 +957,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 +977,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 +989,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 +1004,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); From 6faa40d40626f8301b5f977720b9ed7e5dfbf401 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 25 Apr 2022 14:26:41 +0200 Subject: [PATCH 04/14] Migrate source-script to ES6 --- .../html/static/js/source-script.js | 89 ++++++++++--------- 1 file changed, 45 insertions(+), 44 deletions(-) diff --git a/src/librustdoc/html/static/js/source-script.js b/src/librustdoc/html/static/js/source-script.js index aa77e62ba5a..c48a847665e 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); } From 724c4bd9bb011d331074618ebb739d6ed3e3e0b4 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 25 Apr 2022 14:33:53 +0200 Subject: [PATCH 05/14] Migrate storage.js to ES6 --- src/librustdoc/html/static/js/storage.js | 47 +++++++++++++----------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js index ccf3d0a581a..ae670ed9894 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); From 509b145744ee0f441d9cba092831372c5029f716 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 25 Apr 2022 14:53:55 +0200 Subject: [PATCH 06/14] Migrate scrape-examples.js to ES6 --- .../html/static/js/scrape-examples.js | 45 ++++++++++--------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/src/librustdoc/html/static/js/scrape-examples.js b/src/librustdoc/html/static/js/scrape-examples.js index a28fb461729..865ed7190f3 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
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}); }); })(); From 4e0be6ddeb7e05c5b9998f011175c22bca11d68e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 25 Apr 2022 16:53:59 +0200 Subject: [PATCH 07/14] Remove dead code in main.js --- src/librustdoc/html/static/js/main.js | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index cc9dc0adbca..9e5de9a843a 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -504,29 +504,6 @@ function hideThemeButtonState() { document.addEventListener("keypress", handleShortcut); document.addEventListener("keydown", handleShortcut); - (function() { - const x = document.getElementsByClassName("version-selector"); - if (x.length > 0) { - x[0].onchange = function() { - let url = document.location.href, stripped = ""; - const len = window.rootPath.match(/\.\.\//g).length + 1; - - for (let i = 0; i < len; ++i) { - const match = url.match(/\/[^/]*$/); - if (i < len - 1) { - stripped = match[0] + stripped; - } - url = url.substring(0, url.length - match[0].length); - } - - const selectedVersion = document.getElementsByClassName("version-selector")[0].value; - url += "/" + selectedVersion + stripped; - - document.location.href = url; - }; - } - }()); - // delayed sidebar rendering. window.initSidebarItems = function(items) { const sidebar = document.getElementsByClassName("sidebar-elems")[0]; From e8ae06a31bcfa8b276664323fb825af5fce0a885 Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Thu, 28 Apr 2022 13:53:52 -0400 Subject: [PATCH 08/14] RustWrapper: explicitly don't handle DXILPointerTyID This new enum entry was introduced in https://reviews.llvm.org/D122268, and if I'm reading correctly there's no case where we'd ever encounter it in our uses of LLVM. To preserve the ability to compile this file with -Werror -Wswitch we add an explicit case for this entry. --- compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 850b80e4280..6d79e662a42 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."); } From 346065f621c861179a4f51d701c9c7c7a907346b Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Thu, 28 Apr 2022 16:45:05 -0700 Subject: [PATCH 09/14] rustdoc: fix missing method list for primitive deref target This change makes it so that local impls count when listing primitives that need retained. --- src/librustdoc/passes/collect_trait_impls.rs | 73 ++++++++++---------- src/test/rustdoc/deref-slice-core.rs | 22 ++++++ 2 files changed, 60 insertions(+), 35 deletions(-) create mode 100644 src/test/rustdoc/deref-slice-core.rs diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 6962b5c7ee3..7b6b1ba0d96 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -33,13 +33,42 @@ 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 @@ 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 @@ 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))); } } } @@ -90,7 +119,7 @@ fn add_deref_target( } // 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) @@ -122,7 +151,8 @@ fn add_deref_target( } } - 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 +164,10 @@ fn add_deref_target( } }); - // 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/rustdoc/deref-slice-core.rs b/src/test/rustdoc/deref-slice-core.rs new file mode 100644 index 00000000000..cccf273a820 --- /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' +// @has '-' '//*[@class="impl-items"]//*[@id="method.len"]' 'pub fn len(&self)' + +pub struct MyArray { + array: [T; 10], +} + +impl Deref for MyArray { + type Target = [T]; + + fn deref(&self) -> &Self::Target { + &self.array + } +} From 8743ce85231d1b889323286aa3c88e0cfbc1a76b Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 29 Apr 2022 08:49:14 -0700 Subject: [PATCH 10/14] rustdoc: prevent B -> C -> B -> C loops from stack overflowing --- src/librustdoc/passes/collect_trait_impls.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 7b6b1ba0d96..9644e3d15fd 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -100,6 +100,7 @@ fn add_deref_target( cx: &DocContext<'_>, map: &FxHashMap, cleaner: &mut BadImplStripper<'_>, + targets: &mut FxHashSet, type_did: DefId, ) { if let Some(target) = map.get(&type_did) { @@ -108,12 +109,12 @@ fn add_deref_target( cleaner.prims.insert(target_prim); } else if let Some(target_did) = target.def_id(&cx.cache) { // `impl Deref 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); } } } @@ -143,7 +144,15 @@ fn add_deref_target( // `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, + ); } } } From f66de50f8a0b98f539f9882115cb1d1aa4c8e182 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Fri, 29 Apr 2022 18:48:48 +0200 Subject: [PATCH 11/14] Use the correct lifetime binder for elided lifetimes in path. --- compiler/rustc_resolve/src/late.rs | 25 +++++++++++-------- .../elided-lifetime-in-path-in-impl-Fn.rs | 19 ++++++++++++++ 2 files changed, 33 insertions(+), 11 deletions(-) create mode 100644 src/test/ui/lifetimes/elided-lifetime-in-path-in-impl-Fn.rs diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 9ea66c0b59d..31f30f39c87 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1319,7 +1319,8 @@ fn resolve_elided_lifetimes_in_path( | PathSource::Struct | PathSource::TupleStruct(..) => false, }; - let mut error = false; + let mut error = true; + 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 +1330,6 @@ fn resolve_elided_lifetimes_in_path( // impl Foo for std::cell::Ref // note lack of '_ // async fn foo(_: std::cell::Ref) { ... } LifetimeRibKind::AnonymousCreateParameter(_) => { - error = true; break; } // `PassThrough` is the normal case. @@ -1338,19 +1338,22 @@ fn resolve_elided_lifetimes_in_path( // `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) => { + error = false; + 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. + res = LifetimeRes::Anonymous { binder: DUMMY_NODE_ID, elided: true }; + error = false; + 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, 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 00000000000..9c9965d8fb8 --- /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() +where + T: Fn(Foo), +{ +} + +fn main() {} From 7704cf2c5dd54a8e7a2d626e1ba0ebc8f8674909 Mon Sep 17 00:00:00 2001 From: Andrew Brown Date: Fri, 29 Apr 2022 10:32:34 -0700 Subject: [PATCH 12/14] Remove unnecessary environment variable in cf-protection documentation Before merging the `cf-protection` flag, it was necessary to use a locally-compiled version of `rustc`. This is no longer the case and the documentation should reflect this. --- src/doc/unstable-book/src/compiler-flags/cf-protection.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 cc580ca9b42..ab698c82ba9 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 From 3614bd3c45a8d0e5f27c0736e8966f6456a5cd75 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Fri, 29 Apr 2022 19:36:02 +0200 Subject: [PATCH 13/14] Fix duplicate directory separator in --remap-path-prefix. --- compiler/rustc_span/src/source_map.rs | 14 +++- compiler/rustc_span/src/source_map/tests.rs | 80 +++++++++++++++++++++ src/test/codegen/remap_path_prefix/main.rs | 2 +- 3 files changed, 94 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index 95177102dcf..460b5c18fc1 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -1102,7 +1102,19 @@ pub fn map_prefix(&self, path: PathBuf) -> (PathBuf, bool) { // 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 f13979941ab..481e015c66c 100644 --- a/compiler/rustc_span/src/source_map/tests.rs +++ b/compiler/rustc_span/src/source_map/tests.rs @@ -312,3 +312,83 @@ fn span_substr( } } } + +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/test/codegen/remap_path_prefix/main.rs b/src/test/codegen/remap_path_prefix/main.rs index 698dfe6b4f3..b13d576295c 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: "" From 6e349c7f075d6791eec4c90aa3f2865dfd594da7 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Fri, 29 Apr 2022 22:26:22 +0200 Subject: [PATCH 14/14] Remove `error` variable. --- compiler/rustc_resolve/src/late.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 31f30f39c87..21b888c25c2 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1319,7 +1319,6 @@ fn resolve_elided_lifetimes_in_path( | PathSource::Struct | PathSource::TupleStruct(..) => false, }; - let mut error = true; let mut res = LifetimeRes::Error; for rib in self.lifetime_ribs.iter().rev() { match rib.kind { @@ -1339,15 +1338,14 @@ fn resolve_elided_lifetimes_in_path( // lifetime. Instead, we simply create an implicit lifetime, which will be checked // later, at which point a suitable error will be emitted. LifetimeRibKind::AnonymousPassThrough(binder) => { - error = false; 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. + // since these cases are erroneous anyway. Lifetime resolution should + // emit a "missing lifetime specifier" diagnostic. res = LifetimeRes::Anonymous { binder: DUMMY_NODE_ID, elided: true }; - error = false; break; } _ => {} @@ -1377,7 +1375,7 @@ fn resolve_elided_lifetimes_in_path( // 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,