From 4c2b135fc43ebbaa29cf7526f907ada08b075a04 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 7 Mar 2023 17:41:03 +0100 Subject: Fix invalid inlining of reexport of reexport of private item --- src/librustdoc/clean/mod.rs | 108 +++++++++++++++++++++++++++----------------- src/librustdoc/visit_ast.rs | 20 +++++++- 2 files changed, 85 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index bbd9f18973a..29c3afe0d95 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2065,23 +2065,81 @@ fn clean_bare_fn_ty<'tcx>( BareFunctionDecl { unsafety: bare_fn.unsafety, abi: bare_fn.abi, decl, generic_params } } -/// This visitor is used to go through only the "top level" of a item and not enter any sub -/// item while looking for a given `Ident` which is stored into `item` if found. -struct OneLevelVisitor<'hir> { +/// Get DefId of of an item's user-visible parent. +/// +/// "User-visible" should account for re-exporting and inlining, which is why this function isn't +/// just `tcx.parent(def_id)`. If the provided `path` has more than one path element, the `DefId` +/// of the second-to-last will be given. +/// +/// ```text +/// use crate::foo::Bar; +/// ^^^ DefId of this item will be returned +/// ``` +/// +/// If the provided path has only one item, `tcx.parent(def_id)` will be returned instead. +fn get_path_parent_def_id( + tcx: TyCtxt<'_>, + def_id: DefId, + path: &hir::UsePath<'_>, +) -> Option { + if let [.., parent_segment, _] = &path.segments { + match parent_segment.res { + hir::def::Res::Def(_, parent_def_id) => Some(parent_def_id), + _ if parent_segment.ident.name == kw::Crate => { + // In case the "parent" is the crate, it'll give `Res::Err` so we need to + // circumvent it this way. + Some(tcx.parent(def_id)) + } + _ => None, + } + } else { + // If the path doesn't have a parent, then the parent is the current module. + Some(tcx.parent(def_id)) + } +} + +/// This visitor is used to find an HIR Item based on its `use` path. This doesn't use the ordinary +/// name resolver because it does not walk all the way through a chain of re-exports. +pub(crate) struct OneLevelVisitor<'hir> { map: rustc_middle::hir::map::Map<'hir>, - item: Option<&'hir hir::Item<'hir>>, + pub(crate) item: Option<&'hir hir::Item<'hir>>, looking_for: Ident, target_def_id: LocalDefId, } impl<'hir> OneLevelVisitor<'hir> { - fn new(map: rustc_middle::hir::map::Map<'hir>, target_def_id: LocalDefId) -> Self { + pub(crate) fn new(map: rustc_middle::hir::map::Map<'hir>, target_def_id: LocalDefId) -> Self { Self { map, item: None, looking_for: Ident::empty(), target_def_id } } - fn reset(&mut self, looking_for: Ident) { - self.looking_for = looking_for; + pub(crate) fn find_target( + &mut self, + tcx: TyCtxt<'_>, + def_id: DefId, + path: &hir::UsePath<'_>, + ) -> Option<&'hir hir::Item<'hir>> { + let parent_def_id = get_path_parent_def_id(tcx, def_id, path)?; + let parent = self.map.get_if_local(parent_def_id)?; + + // We get the `Ident` we will be looking for into `item`. + self.looking_for = path.segments[path.segments.len() - 1].ident; + // We reset the `item`. self.item = None; + + match parent { + hir::Node::Item(parent_item) => { + hir::intravisit::walk_item(self, parent_item); + } + hir::Node::Crate(m) => { + hir::intravisit::walk_mod( + self, + m, + tcx.local_def_id_to_hir_id(parent_def_id.as_local().unwrap()), + ); + } + _ => return None, + } + self.item } } @@ -2129,41 +2187,7 @@ fn get_all_import_attributes<'hir>( add_without_unwanted_attributes(attributes, hir_map.attrs(item.hir_id()), is_inline); } - let def_id = if let [.., parent_segment, _] = &path.segments { - match parent_segment.res { - hir::def::Res::Def(_, def_id) => def_id, - _ if parent_segment.ident.name == kw::Crate => { - // In case the "parent" is the crate, it'll give `Res::Err` so we need to - // circumvent it this way. - tcx.parent(item.owner_id.def_id.to_def_id()) - } - _ => break, - } - } else { - // If the path doesn't have a parent, then the parent is the current module. - tcx.parent(item.owner_id.def_id.to_def_id()) - }; - - let Some(parent) = hir_map.get_if_local(def_id) else { break }; - - // We get the `Ident` we will be looking for into `item`. - let looking_for = path.segments[path.segments.len() - 1].ident; - visitor.reset(looking_for); - - match parent { - hir::Node::Item(parent_item) => { - hir::intravisit::walk_item(&mut visitor, parent_item); - } - hir::Node::Crate(m) => { - hir::intravisit::walk_mod( - &mut visitor, - m, - tcx.local_def_id_to_hir_id(def_id.as_local().unwrap()), - ); - } - _ => break, - } - if let Some(i) = visitor.item { + if let Some(i) = visitor.find_target(tcx, item.owner_id.def_id.to_def_id(), path) { item = i; } else { break; diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 5bbbff175cf..44e9b49f82a 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -15,7 +15,7 @@ use rustc_span::Span; use std::mem; -use crate::clean::{cfg::Cfg, AttributesExt, NestedAttributesExt}; +use crate::clean::{cfg::Cfg, AttributesExt, NestedAttributesExt, OneLevelVisitor}; use crate::core; /// This module is used to store stuff from Rust's AST in a more convenient @@ -220,6 +220,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { renamed: Option, glob: bool, please_inline: bool, + path: &hir::UsePath<'_>, ) -> bool { debug!("maybe_inline_local res: {:?}", res); @@ -263,6 +264,22 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { return false; } + if !please_inline && + let mut visitor = OneLevelVisitor::new(self.cx.tcx.hir(), res_did) && + let Some(item) = visitor.find_target(self.cx.tcx, def_id.to_def_id(), path) && + let item_def_id = item.owner_id.def_id && + item_def_id != def_id && + self + .cx + .cache + .effective_visibilities + .is_directly_public(self.cx.tcx, item_def_id.to_def_id()) && + !inherits_doc_hidden(self.cx.tcx, item_def_id) + { + // The imported item is public and not `doc(hidden)` so no need to inline it. + return false; + } + let ret = match tcx.hir().get_by_def_id(res_did) { Node::Item(&hir::Item { kind: hir::ItemKind::Mod(ref m), .. }) if glob => { let prev = mem::replace(&mut self.inlining, true); @@ -361,6 +378,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { ident, is_glob, please_inline, + path, ) { continue; } -- cgit 1.4.1-3-g733a5 From d75dae2df200853aa498ac2083c68ff243be9666 Mon Sep 17 00:00:00 2001 From: Ayush Singh Date: Thu, 9 Mar 2023 01:03:07 +0530 Subject: Consider target_family as pal Currently tidy does not consider code in target_family as platform-specific. I think this is erroneous and should be fixed. Signed-off-by: Ayush Singh --- src/tools/tidy/src/pal.rs | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs index 33938ac9a0a..6d6d3c89a3c 100644 --- a/src/tools/tidy/src/pal.rs +++ b/src/tools/tidy/src/pal.rs @@ -62,6 +62,8 @@ const EXCEPTION_PATHS: &[&str] = &[ "library/std/src/panic.rs", // fuchsia-specific panic backtrace handling "library/std/src/personality.rs", "library/std/src/personality/", + "library/std/src/thread/mod.rs", + "library/std/src/thread/local.rs", ]; pub fn check(path: &Path, bad: &mut bool) { @@ -128,6 +130,7 @@ fn check_cfgs( || cfg.contains("target_env") || cfg.contains("target_abi") || cfg.contains("target_vendor") + || cfg.contains("target_family") || cfg.contains("unix") || cfg.contains("windows"); -- cgit 1.4.1-3-g733a5 From f916681d8d435428a8fe09213e1640e3290f2df7 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sun, 15 Jan 2023 11:34:58 -0700 Subject: Only load one CSS theme by default To avoid generating a FOUC at startup, this commit uses `document.write` to load the stylesheet initially. Co-Authored-By: Guillaume Gomez --- src/librustdoc/html/render/context.rs | 28 +++++++++++++++++-- src/librustdoc/html/static/js/main.js | 39 ++++++++++++++++++--------- src/librustdoc/html/static/js/storage.js | 46 +++++++++++++++++--------------- src/librustdoc/html/templates/page.html | 39 ++++++++++++++------------- 4 files changed, 99 insertions(+), 53 deletions(-) (limited to 'src') diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 5e4a595627b..ea5a4590f33 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -649,11 +649,35 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { \ \ - ", + \ + \ + \ + ", static_root_path = page.get_static_root_path(), settings_css = static_files::STATIC_FILES.settings_css, settings_js = static_files::STATIC_FILES.settings_js, - ) + theme_light_css = static_files::STATIC_FILES.theme_light_css, + theme_dark_css = static_files::STATIC_FILES.theme_dark_css, + theme_ayu_css = static_files::STATIC_FILES.theme_ayu_css, + ); + // Pre-load all theme CSS files, so that switching feels seamless. + // + // When loading settings.html as a popover, the equivalent HTML is + // generated in main.js. + for file in &shared.style_files { + if let Ok(theme) = file.basename() { + write!( + buf, + "", + root_path = page.static_root_path.unwrap_or(""), + suffix = page.resource_suffix, + ); + } + } }, &shared.style_files, ); diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 5e8c0e8d10c..403b5004d65 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -1,20 +1,9 @@ // Local js definitions: /* global addClass, getSettingValue, hasClass, searchState */ -/* global onEach, onEachLazy, removeClass */ +/* global onEach, onEachLazy, removeClass, getVar */ "use strict"; -// 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) { - const el = document.getElementById("rustdoc-vars"); - if (el) { - return el.attributes["data-" + name].value; - } else { - return null; - } -} - // Given a basename (e.g. "storage") and an extension (e.g. ".js"), return a URL // for a resource under the root-path, with the resource-suffix. function resourcePath(basename, extension) { @@ -187,6 +176,15 @@ function loadCss(cssUrl) { document.getElementsByTagName("head")[0].appendChild(link); } +function preLoadCss(cssUrl) { + // https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/preload + const link = document.createElement("link"); + link.href = cssUrl; + link.rel = "preload"; + link.as = "style"; + document.getElementsByTagName("head")[0].appendChild(link); +} + (function() { const isHelpPage = window.location.pathname.endsWith("/help.html"); @@ -207,6 +205,23 @@ function loadCss(cssUrl) { // hopefully be loaded when the JS will generate the settings content. loadCss(getVar("static-root-path") + getVar("settings-css")); loadScript(getVar("static-root-path") + getVar("settings-js")); + preLoadCss(getVar("static-root-path") + getVar("theme-light-css")); + preLoadCss(getVar("static-root-path") + getVar("theme-dark-css")); + preLoadCss(getVar("static-root-path") + getVar("theme-ayu-css")); + // Pre-load all theme CSS files, so that switching feels seamless. + // + // When loading settings.html as a standalone page, the equivalent HTML is + // generated in context.rs. + setTimeout(() => { + const themes = getVar("themes").split(","); + for (const theme of themes) { + // if there are no themes, do nothing + // "".split(",") == [""] + if (theme !== "") { + preLoadCss(getVar("root-path") + theme + ".css"); + } + } + }, 0); }; window.searchState = { diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js index c72ac254fc0..1e16f34a3eb 100644 --- a/src/librustdoc/html/static/js/storage.js +++ b/src/librustdoc/html/static/js/storage.js @@ -7,7 +7,6 @@ const darkThemes = ["dark", "ayu"]; window.currentTheme = document.getElementById("themeStyle"); -window.mainTheme = document.getElementById("mainThemeStyle"); // WARNING: RUSTDOC_MOBILE_BREAKPOINT MEDIA QUERY // If you update this line, then you also need to update the media query with the same @@ -44,8 +43,6 @@ function getSettingValue(settingName) { const localStoredTheme = getSettingValue("theme"); -const savedHref = []; - // eslint-disable-next-line no-unused-vars function hasClass(elem, className) { return elem && elem.classList && elem.classList.contains(className); @@ -125,30 +122,37 @@ function getCurrentValue(name) { } } -function switchTheme(styleElem, mainStyleElem, newThemeName, saveTheme) { +// 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. +const getVar = (function getVar(name) { + const el = document.getElementById("rustdoc-vars"); + if (el) { + return el.attributes["data-" + name].value; + } else { + return null; + } +}); + +function switchTheme(newThemeName, saveTheme) { // If this new value comes from a system setting or from the previously // saved theme, no need to save it. if (saveTheme) { updateLocalStorage("theme", newThemeName); } - if (savedHref.length === 0) { - onEachLazy(document.getElementsByTagName("link"), el => { - savedHref.push(el.href); - }); + let newHref; + + if (newThemeName === "light" || newThemeName === "dark" || newThemeName === "ayu") { + newHref = getVar("static-root-path") + getVar("theme-" + newThemeName + "-css"); + } else { + newHref = getVar("root-path") + newThemeName + getVar("resource-suffix") + ".css"; } - const newHref = savedHref.find(url => { - const m = url.match(/static\.files\/(.*)-[a-f0-9]{16}\.css$/); - if (m && m[1] === newThemeName) { - return true; - } - const m2 = url.match(/\/([^/]*)\.css$/); - if (m2 && m2[1].startsWith(newThemeName)) { - return true; - } - }); - if (newHref && newHref !== styleElem.href) { - styleElem.href = newHref; + + if (!window.currentTheme) { + document.write(""); + window.currentTheme = document.getElementById("themeStyle"); + } else if (newHref !== window.currentTheme.href) { + window.currentTheme.href = newHref; } } @@ -164,7 +168,7 @@ const updateTheme = (function() { */ function updateTheme() { const use = (theme, saveTheme) => { - switchTheme(window.currentTheme, window.mainTheme, theme, saveTheme); + switchTheme(theme, saveTheme); }; // maybe the user has disabled the setting in the meantime! diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html index e896850fab6..532660e3d33 100644 --- a/src/librustdoc/html/templates/page.html +++ b/src/librustdoc/html/templates/page.html @@ -17,12 +17,6 @@ {# #} - {# #} - {# #} - {# #} - {% for theme in themes %} - {# #} - {% endfor %} {% if !layout.default_settings.is_empty() %} {# #} {% endif %} +
{# #} +
{# #} {# #} {% if page.css_class.contains("crate") %} {# #} @@ -44,6 +53,12 @@ {# #} {% endif %} {# #} @@ -132,17 +147,5 @@ {% if page.css_class != "source" %}{% endif %} {# #} {{ layout.external_html.after_content|safe }} -
{# #} -
{# #} {# #} {# #} -- cgit 1.4.1-3-g733a5 From 5db516b80972ea23cccb3722f289a8be5c0ee486 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 4 Nov 2022 20:26:42 +0100 Subject: Fix eslint errors --- src/librustdoc/html/static/js/storage.js | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js index 1e16f34a3eb..7b3e702010a 100644 --- a/src/librustdoc/html/static/js/storage.js +++ b/src/librustdoc/html/static/js/storage.js @@ -99,6 +99,7 @@ function onEach(arr, func, reversed) { * @param {function(?)} func - The callback * @param {boolean} [reversed] - Whether to iterate in reverse */ +// eslint-disable-next-line no-unused-vars function onEachLazy(lazyArray, func, reversed) { return onEach( Array.prototype.slice.call(lazyArray), -- cgit 1.4.1-3-g733a5 From 255fdb398ecaa36a274b7ef6c5760233187dc3ad Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 18 Feb 2023 10:28:58 -0700 Subject: Update src/librustdoc/html/static/js/storage.js Co-authored-by: Guillaume Gomez --- src/librustdoc/html/static/js/storage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js index 7b3e702010a..c3fed9a72d4 100644 --- a/src/librustdoc/html/static/js/storage.js +++ b/src/librustdoc/html/static/js/storage.js @@ -150,7 +150,7 @@ function switchTheme(newThemeName, saveTheme) { } if (!window.currentTheme) { - document.write(""); + document.write(``); window.currentTheme = document.getElementById("themeStyle"); } else if (newHref !== window.currentTheme.href) { window.currentTheme.href = newHref; -- cgit 1.4.1-3-g733a5 From eb9b031232160063e1fb4b3a865607e6dcc95129 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 5 Mar 2023 15:05:59 +0000 Subject: Don't print all modified files if there's more than 10 This avoids spam for dozens of modified files. --- src/bootstrap/format.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/bootstrap/format.rs b/src/bootstrap/format.rs index 6d5753e8a6d..32a5f5b93c6 100644 --- a/src/bootstrap/format.rs +++ b/src/bootstrap/format.rs @@ -159,8 +159,14 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { if !check && paths.is_empty() { match get_modified_rs_files(build) { Ok(Some(files)) => { + if files.len() <= 10 { + for file in &files { + println!("formatting modified file {file}"); + } + } else { + println!("formatting {} modified files", files.len()); + } for file in files { - println!("formatting modified file {file}"); ignore_fmt.add(&format!("/{file}")).expect(&file); } } -- cgit 1.4.1-3-g733a5 From 18667722e2b65bfce98468738ffa1d95ba0f71fd Mon Sep 17 00:00:00 2001 From: Ikko Eltociear Ashimine Date: Thu, 9 Mar 2023 14:47:42 +0900 Subject: Fix typo in span_map.rs correspondance -> correspondence --- src/librustdoc/html/render/span_map.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs index 4514894cabe..eb9262f472b 100644 --- a/src/librustdoc/html/render/span_map.rs +++ b/src/librustdoc/html/render/span_map.rs @@ -29,12 +29,12 @@ pub(crate) enum LinkFromSrc { /// This function will do at most two things: /// -/// 1. Generate a `span` correspondance map which links an item `span` to its definition `span`. +/// 1. Generate a `span` correspondence map which links an item `span` to its definition `span`. /// 2. Collect the source code files. /// -/// It returns the `krate`, the source code files and the `span` correspondance map. +/// It returns the `krate`, the source code files and the `span` correspondence map. /// -/// Note about the `span` correspondance map: the keys are actually `(lo, hi)` of `span`s. We don't +/// Note about the `span` correspondence map: the keys are actually `(lo, hi)` of `span`s. We don't /// need the `span` context later on, only their position, so instead of keep a whole `Span`, we /// only keep the `lo` and `hi`. pub(crate) fn collect_spans_and_sources( -- cgit 1.4.1-3-g733a5