Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit a522d78

Browse files
committed
Auto merge of #133345 - GuillaumeGomez:stop-cloning-context, r=notriddle,aDotInTheVoid
Stop cloning `Context` so much This is a first step for #82381. It's already big enough so I'll continue in a follow-up once this PR is merged. Next step will be to get rid of `SharedContext` by inlining it directly into `Context`. cc `@camelid` r? `@notriddle`
2 parents 5e1440a + 69ed026 commit a522d78

File tree

9 files changed

+355
-285
lines changed

9 files changed

+355
-285
lines changed

‎src/librustdoc/formats/renderer.rs‎

Lines changed: 63 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1+
use rustc_data_structures::profiling::SelfProfilerRef;
12
use rustc_middle::ty::TyCtxt;
2-
use tracing::debug;
33

44
use crate::clean;
55
use crate::config::RenderOptions;
@@ -17,6 +17,18 @@ pub(crate) trait FormatRenderer<'tcx>: Sized {
1717
///
1818
/// This is true for html, and false for json. See #80664
1919
const RUN_ON_MODULE: bool;
20+
/// This associated type is the type where the current module information is stored.
21+
///
22+
/// For each module, we go through their items by calling for each item:
23+
///
24+
/// 1. save_module_data
25+
/// 2. item
26+
/// 3. set_back_info
27+
///
28+
/// However,the `item` method might update information in `self` (for example if the child is
29+
/// a module). To prevent it to impact the other children of the current module, we need to
30+
/// reset the information between each call to `item` by using `set_back_info`.
31+
type ModuleData;
2032

2133
/// Sets up any state required for the renderer. When this is called the cache has already been
2234
/// populated.
@@ -27,8 +39,20 @@ pub(crate) trait FormatRenderer<'tcx>: Sized {
2739
tcx: TyCtxt<'tcx>,
2840
) -> Result<(Self, clean::Crate), Error>;
2941

30-
/// Make a new renderer to render a child of the item currently being rendered.
31-
fn make_child_renderer(&self) -> Self;
42+
/// This method is called right before call [`Self::item`]. This method returns a type
43+
/// containing information that needs to be reset after the [`Self::item`] method has been
44+
/// called with the [`Self::set_back_info`] method.
45+
///
46+
/// In short it goes like this:
47+
///
48+
/// ```ignore (not valid code)
49+
/// let reset_data = type.save_module_data();
50+
/// type.item(item)?;
51+
/// type.set_back_info(reset_data);
52+
/// ```
53+
fn save_module_data(&mut self) -> Self::ModuleData;
54+
/// Used to reset current module's information.
55+
fn set_back_info(&mut self, info: Self::ModuleData);
3256

3357
/// Renders a single non-module item. This means no recursive sub-item rendering is required.
3458
fn item(&mut self, item: clean::Item) -> Result<(), Error>;
@@ -47,6 +71,40 @@ pub(crate) trait FormatRenderer<'tcx>: Sized {
4771
fn cache(&self) -> &Cache;
4872
}
4973

74+
fn run_format_inner<'tcx, T: FormatRenderer<'tcx>>(
75+
cx: &mut T,
76+
item: clean::Item,
77+
prof: &SelfProfilerRef,
78+
) -> Result<(), Error> {
79+
if item.is_mod() && T::RUN_ON_MODULE {
80+
// modules are special because they add a namespace. We also need to
81+
// recurse into the items of the module as well.
82+
let _timer =
83+
prof.generic_activity_with_arg("render_mod_item", item.name.unwrap().to_string());
84+
85+
cx.mod_item_in(&item)?;
86+
let (clean::StrippedItem(box clean::ModuleItem(module)) | clean::ModuleItem(module)) =
87+
item.inner.kind
88+
else {
89+
unreachable!()
90+
};
91+
for it in module.items {
92+
let info = cx.save_module_data();
93+
run_format_inner(cx, it, prof)?;
94+
cx.set_back_info(info);
95+
}
96+
97+
cx.mod_item_out()?;
98+
// FIXME: checking `item.name.is_some()` is very implicit and leads to lots of special
99+
// cases. Use an explicit match instead.
100+
} else if let Some(item_name) = item.name
101+
&& !item.is_extern_crate()
102+
{
103+
prof.generic_activity_with_arg("render_item", item_name.as_str()).run(|| cx.item(item))?;
104+
}
105+
Ok(())
106+
}
107+
50108
/// Main method for rendering a crate.
51109
pub(crate) fn run_format<'tcx, T: FormatRenderer<'tcx>>(
52110
krate: clean::Crate,
@@ -66,36 +124,8 @@ pub(crate) fn run_format<'tcx, T: FormatRenderer<'tcx>>(
66124
}
67125

68126
// Render the crate documentation
69-
let mut work = vec![(format_renderer.make_child_renderer(), krate.module)];
70-
71-
while let Some((mut cx, item)) = work.pop() {
72-
if item.is_mod() && T::RUN_ON_MODULE {
73-
// modules are special because they add a namespace. We also need to
74-
// recurse into the items of the module as well.
75-
let _timer =
76-
prof.generic_activity_with_arg("render_mod_item", item.name.unwrap().to_string());
77-
78-
cx.mod_item_in(&item)?;
79-
let (clean::StrippedItem(box clean::ModuleItem(module)) | clean::ModuleItem(module)) =
80-
item.inner.kind
81-
else {
82-
unreachable!()
83-
};
84-
for it in module.items {
85-
debug!("Adding {:?} to worklist", it.name);
86-
work.push((cx.make_child_renderer(), it));
87-
}
88-
89-
cx.mod_item_out()?;
90-
// FIXME: checking `item.name.is_some()` is very implicit and leads to lots of special
91-
// cases. Use an explicit match instead.
92-
} else if let Some(item_name) = item.name
93-
&& !item.is_extern_crate()
94-
{
95-
prof.generic_activity_with_arg("render_item", item_name.as_str())
96-
.run(|| cx.item(item))?;
97-
}
98-
}
127+
run_format_inner(&mut format_renderer, krate.module, prof)?;
128+
99129
prof.verbose_generic_activity_with_arg("renderer_after_krate", T::descr())
100130
.run(|| format_renderer.after_krate())
101131
}

‎src/librustdoc/html/markdown.rs‎

Lines changed: 66 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ use std::sync::OnceLock;
3737
use pulldown_cmark::{
3838
BrokenLink, CodeBlockKind, CowStr, Event, LinkType, Options, Parser, Tag, TagEnd, html,
3939
};
40-
use rustc_data_structures::fx::FxHashMap;
40+
use rustc_data_structures::fx::{FxHashMap,FxHashSet};
4141
use rustc_errors::{Diag, DiagMessage};
4242
use rustc_hir::def_id::LocalDefId;
4343
use rustc_middle::ty::TyCtxt;
@@ -1886,71 +1886,81 @@ pub struct IdMap {
18861886
existing_footnotes: usize,
18871887
}
18881888

1889-
// The map is pre-initialized and cloned each time to avoid reinitializing it repeatedly.
1890-
static DEFAULT_ID_MAP: OnceLock<FxHashMap<Cow<'static, str>, usize>> = OnceLock::new();
1889+
// The map is pre-initialized and then can be used as is to prevent cloning it for each item
1890+
// (in the sidebar rendering).
1891+
static DEFAULT_ID_MAP: OnceLock<FxHashSet<&'static str>> = OnceLock::new();
18911892

1892-
fn init_id_map() -> FxHashMap<Cow<'static, str>,usize> {
1893-
let mut map = FxHashMap::default();
1893+
fn init_id_map() -> FxHashSet<&'static str> {
1894+
let mut map = FxHashSet::default();
18941895
// This is the list of IDs used in JavaScript.
1895-
map.insert("help".into(),1);
1896-
map.insert("settings".into(),1);
1897-
map.insert("not-displayed".into(),1);
1898-
map.insert("alternative-display".into(),1);
1899-
map.insert("search".into(),1);
1900-
map.insert("crate-search".into(),1);
1901-
map.insert("crate-search-div".into(),1);
1896+
map.insert("help");
1897+
map.insert("settings");
1898+
map.insert("not-displayed");
1899+
map.insert("alternative-display");
1900+
map.insert("search");
1901+
map.insert("crate-search");
1902+
map.insert("crate-search-div");
19021903
// This is the list of IDs used in HTML generated in Rust (including the ones
19031904
// used in tera template files).
1904-
map.insert("themeStyle".into(),1);
1905-
map.insert("settings-menu".into(),1);
1906-
map.insert("help-button".into(),1);
1907-
map.insert("sidebar-button".into(),1);
1908-
map.insert("main-content".into(),1);
1909-
map.insert("toggle-all-docs".into(),1);
1910-
map.insert("all-types".into(),1);
1911-
map.insert("default-settings".into(),1);
1912-
map.insert("sidebar-vars".into(),1);
1913-
map.insert("copy-path".into(),1);
1914-
map.insert("rustdoc-toc".into(),1);
1915-
map.insert("rustdoc-modnav".into(),1);
1905+
map.insert("themeStyle");
1906+
map.insert("settings-menu");
1907+
map.insert("help-button");
1908+
map.insert("sidebar-button");
1909+
map.insert("main-content");
1910+
map.insert("toggle-all-docs");
1911+
map.insert("all-types");
1912+
map.insert("default-settings");
1913+
map.insert("sidebar-vars");
1914+
map.insert("copy-path");
1915+
map.insert("rustdoc-toc");
1916+
map.insert("rustdoc-modnav");
19161917
// This is the list of IDs used by rustdoc sections (but still generated by
19171918
// rustdoc).
1918-
map.insert("fields".into(),1);
1919-
map.insert("variants".into(),1);
1920-
map.insert("implementors-list".into(),1);
1921-
map.insert("synthetic-implementors-list".into(),1);
1922-
map.insert("foreign-impls".into(),1);
1923-
map.insert("implementations".into(),1);
1924-
map.insert("trait-implementations".into(),1);
1925-
map.insert("synthetic-implementations".into(),1);
1926-
map.insert("blanket-implementations".into(),1);
1927-
map.insert("required-associated-types".into(),1);
1928-
map.insert("provided-associated-types".into(),1);
1929-
map.insert("provided-associated-consts".into(),1);
1930-
map.insert("required-associated-consts".into(),1);
1931-
map.insert("required-methods".into(),1);
1932-
map.insert("provided-methods".into(),1);
1933-
map.insert("dyn-compatibility".into(),1);
1934-
map.insert("implementors".into(),1);
1935-
map.insert("synthetic-implementors".into(),1);
1936-
map.insert("implementations-list".into(),1);
1937-
map.insert("trait-implementations-list".into(),1);
1938-
map.insert("synthetic-implementations-list".into(),1);
1939-
map.insert("blanket-implementations-list".into(),1);
1940-
map.insert("deref-methods".into(),1);
1941-
map.insert("layout".into(),1);
1942-
map.insert("aliased-type".into(),1);
1919+
map.insert("fields");
1920+
map.insert("variants");
1921+
map.insert("implementors-list");
1922+
map.insert("synthetic-implementors-list");
1923+
map.insert("foreign-impls");
1924+
map.insert("implementations");
1925+
map.insert("trait-implementations");
1926+
map.insert("synthetic-implementations");
1927+
map.insert("blanket-implementations");
1928+
map.insert("required-associated-types");
1929+
map.insert("provided-associated-types");
1930+
map.insert("provided-associated-consts");
1931+
map.insert("required-associated-consts");
1932+
map.insert("required-methods");
1933+
map.insert("provided-methods");
1934+
map.insert("dyn-compatibility");
1935+
map.insert("implementors");
1936+
map.insert("synthetic-implementors");
1937+
map.insert("implementations-list");
1938+
map.insert("trait-implementations-list");
1939+
map.insert("synthetic-implementations-list");
1940+
map.insert("blanket-implementations-list");
1941+
map.insert("deref-methods");
1942+
map.insert("layout");
1943+
map.insert("aliased-type");
19431944
map
19441945
}
19451946

19461947
impl IdMap {
19471948
pub fn new() -> Self {
1948-
IdMap { map: DEFAULT_ID_MAP.get_or_init(init_id_map).clone(), existing_footnotes: 0 }
1949+
IdMap { map: FxHashMap::default(), existing_footnotes: 0 }
19491950
}
19501951

19511952
pub(crate) fn derive<S: AsRef<str> + ToString>(&mut self, candidate: S) -> String {
19521953
let id = match self.map.get_mut(candidate.as_ref()) {
1953-
None => candidate.to_string(),
1954+
None => {
1955+
let candidate = candidate.to_string();
1956+
if DEFAULT_ID_MAP.get_or_init(init_id_map).contains(candidate.as_str()) {
1957+
let id = format!("{}-{}", candidate, 1);
1958+
self.map.insert(candidate.into(), 2);
1959+
id
1960+
} else {
1961+
candidate
1962+
}
1963+
}
19541964
Some(a) => {
19551965
let id = format!("{}-{}", candidate.as_ref(), *a);
19561966
*a += 1;
@@ -1970,4 +1980,9 @@ impl IdMap {
19701980
closure(self, &mut existing_footnotes);
19711981
self.existing_footnotes = existing_footnotes;
19721982
}
1983+
1984+
pub(crate) fn clear(&mut self) {
1985+
self.map.clear();
1986+
self.existing_footnotes = 0;
1987+
}
19731988
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /