Auto merge of #108934 - matthiaskrgr:rollup-vm414p5, r=matthiaskrgr

Rollup of 8 pull requests

Successful merges:

 - #106915 (Only load one CSS theme by default)
 - #108294 (Place binder correctly for arbitrary trait bound suggestion)
 - #108778 (x fmt: Don't print all modified files if there's more than 10)
 - #108854 (feat/refactor: improve errors in case of ident with number at start)
 - #108870 (Fix invalid inlining of reexport of reexport of private item)
 - #108917 (Consider target_family as pal)
 - #108922 (Add auto notification for changes to stable mir)
 - #108929 (Fix typo in span_map.rs)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-03-10 08:09:25 +00:00
commit 104f4300cf
25 changed files with 345 additions and 153 deletions

View file

@ -165,8 +165,14 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) {
if !CiEnv::is_ci() && 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);
}
}

View file

@ -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<DefId> {
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;

View file

@ -647,11 +647,35 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
</noscript>\
<link rel=\"stylesheet\" \
href=\"{static_root_path}{settings_css}\">\
<script defer src=\"{static_root_path}{settings_js}\"></script>",
<script defer src=\"{static_root_path}{settings_js}\"></script>\
<link rel=\"preload\" href=\"{static_root_path}{theme_light_css}\" \
as=\"style\">\
<link rel=\"preload\" href=\"{static_root_path}{theme_dark_css}\" \
as=\"style\">\
<link rel=\"preload\" href=\"{static_root_path}{theme_ayu_css}\" \
as=\"style\">",
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,
"<link rel=\"preload\" href=\"{root_path}{theme}{suffix}.css\" \
as=\"style\">",
root_path = page.static_root_path.unwrap_or(""),
suffix = page.resource_suffix,
);
}
}
},
&shared.style_files,
);

View file

@ -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(

View file

@ -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 = {

View file

@ -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);
@ -102,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),
@ -125,30 +123,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(`<link rel="stylesheet" id="themeStyle" href="${newHref}">`);
window.currentTheme = document.getElementById("themeStyle");
} else if (newHref !== window.currentTheme.href) {
window.currentTheme.href = newHref;
}
}
@ -164,7 +169,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!

View file

@ -17,12 +17,6 @@
<link rel="stylesheet" {#+ #}
href="{{static_root_path|safe}}{{files.rustdoc_css}}" {#+ #}
id="mainThemeStyle"> {# #}
<link rel="stylesheet" id="themeStyle" href="{{static_root_path|safe}}{{files.theme_light_css}}"> {# #}
<link rel="stylesheet" disabled href="{{static_root_path|safe}}{{files.theme_dark_css}}"> {# #}
<link rel="stylesheet" disabled href="{{static_root_path|safe}}{{files.theme_ayu_css}}"> {# #}
{% for theme in themes %}
<link rel="stylesheet" disabled href="{{page.root_path|safe}}{{theme}}{{page.resource_suffix}}.css"> {# #}
{% endfor %}
{% if !layout.default_settings.is_empty() %}
<script id="default-settings" {#+ #}
{%~ for (k, v) in layout.default_settings ~%}
@ -30,6 +24,21 @@
{% endfor %}
></script> {# #}
{% endif %}
<div id="rustdoc-vars" {#+ #}
data-root-path="{{page.root_path|safe}}" {#+ #}
data-static-root-path="{{static_root_path|safe}}" {#+ #}
data-current-crate="{{layout.krate}}" {#+ #}
data-themes="{{themes|join(",") }}" {#+ #}
data-resource-suffix="{{page.resource_suffix}}" {#+ #}
data-rustdoc-version="{{rustdoc_version}}" {#+ #}
data-search-js="{{files.search_js}}" {#+ #}
data-settings-js="{{files.settings_js}}" {#+ #}
data-settings-css="{{files.settings_css}}" {#+ #}
data-theme-light-css="{{files.theme_light_css}}" {#+ #}
data-theme-dark-css="{{files.theme_dark_css}}" {#+ #}
data-theme-ayu-css="{{files.theme_ayu_css}}" {#+ #}
> {# #}
</div> {# #}
<script src="{{static_root_path|safe}}{{files.storage_js}}"></script> {# #}
{% if page.css_class.contains("crate") %}
<script defer src="{{page.root_path|safe}}crates{{page.resource_suffix}}.js"></script> {# #}
@ -44,6 +53,12 @@
<script defer src="{{static_root_path|safe}}{{files.scrape_examples_js}}"></script> {# #}
{% endif %}
<noscript> {# #}
<link rel="stylesheet" {#+ #}
media="(prefers-color-scheme:light)" {#+ #}
href="{{static_root_path|safe}}{{files.theme_light_css}}"> {# #}
<link rel="stylesheet" {#+ #}
media="(prefers-color-scheme:dark)" {#+ #}
href="{{static_root_path|safe}}{{files.theme_dark_css}}"> {# #}
<link rel="stylesheet" {#+ #}
href="{{static_root_path|safe}}{{files.noscript_css}}"> {# #}
</noscript> {# #}
@ -132,17 +147,5 @@
{% if page.css_class != "source" %}</div>{% endif %}
</main> {# #}
{{ layout.external_html.after_content|safe }}
<div id="rustdoc-vars" {#+ #}
data-root-path="{{page.root_path|safe}}" {#+ #}
data-static-root-path="{{static_root_path|safe}}" {#+ #}
data-current-crate="{{layout.krate}}" {#+ #}
data-themes="{{themes|join(",") }}" {#+ #}
data-resource-suffix="{{page.resource_suffix}}" {#+ #}
data-rustdoc-version="{{rustdoc_version}}" {#+ #}
data-search-js="{{files.search_js}}" {#+ #}
data-settings-js="{{files.settings_js}}" {#+ #}
data-settings-css="{{files.settings_css}}" {#+ #}
> {# #}
</div> {# #}
</body> {# #}
</html> {# #}

View file

@ -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<Symbol>,
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;
}

View file

@ -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");