From b808f330edb853e75ffb542e6eddc9df926603eb Mon Sep 17 00:00:00 2001 From: Alona Enraght-Moony Date: Fri, 17 Oct 2025 21:57:46 +0000 Subject: [PATCH] rustdoc: Don't pass `RenderOptions` to `DocContext` `RenderOptions` is full of HTML specific fields. The only ones that `DocContext` needs are `document_private` and `document_hidden`, which are accessable via `Cache` anyway. Part of a larger campeign against `RenderOptions`: https://rust-lang.zulipchat.com/#narrow/channel/266220-t-rustdoc/topic/Using.20.60RenderOptions.60.20in.20less.20places.2E/with/545705812 --- src/librustdoc/clean/inline.rs | 2 +- src/librustdoc/clean/mod.rs | 17 +++++----- src/librustdoc/core.rs | 32 +++++++++---------- src/librustdoc/formats/cache.rs | 8 +++-- .../passes/check_doc_test_visibility.rs | 2 +- .../passes/collect_intra_doc_links.rs | 4 +-- .../passes/lint/redundant_explicit_links.rs | 6 ++-- src/librustdoc/passes/strip_hidden.rs | 4 +-- src/librustdoc/passes/strip_priv_imports.rs | 8 ++--- src/librustdoc/passes/strip_private.rs | 13 +++----- src/librustdoc/visit_ast.rs | 4 +-- src/librustdoc/visit_lib.rs | 3 +- 12 files changed, 50 insertions(+), 53 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index b470af50f68fe..aafc8bd156b84 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -497,7 +497,7 @@ pub(crate) fn build_impl( return; } - let document_hidden = cx.render_options.document_hidden; + let document_hidden = cx.document_hidden(); let (trait_items, generics) = match impl_item { Some(impl_) => ( impl_ diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 4a95f21a3a5bd..ce92947ee1fa6 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -71,7 +71,7 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext< items.extend(doc.foreigns.iter().map(|(item, renamed, import_id)| { let item = clean_maybe_renamed_foreign_item(cx, item, *renamed, *import_id); if let Some(name) = item.name - && (cx.render_options.document_hidden || !item.is_doc_hidden()) + && (cx.document_hidden() || !item.is_doc_hidden()) { inserted.insert((item.type_(), name)); } @@ -82,7 +82,7 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext< return None; } let item = clean_doc_module(x, cx); - if !cx.render_options.document_hidden && item.is_doc_hidden() { + if !cx.document_hidden() && item.is_doc_hidden() { // Hidden modules are stripped at a later stage. // If a hidden module has the same name as a visible one, we want // to keep both of them around. @@ -104,7 +104,7 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext< let v = clean_maybe_renamed_item(cx, item, *renamed, import_ids); for item in &v { if let Some(name) = item.name - && (cx.render_options.document_hidden || !item.is_doc_hidden()) + && (cx.document_hidden() || !item.is_doc_hidden()) { inserted.insert((item.type_(), name)); } @@ -203,7 +203,7 @@ fn generate_item_with_correct_attrs( .get_word_attr(sym::inline) .is_some() || (is_glob_import(cx.tcx, import_id) - && (cx.render_options.document_hidden || !cx.tcx.is_doc_hidden(def_id))); + && (cx.document_hidden() || !cx.tcx.is_doc_hidden(def_id))); attrs.extend(get_all_import_attributes(cx, import_id, def_id, is_inline)); is_inline = is_inline || import_is_inline; } @@ -1581,9 +1581,9 @@ fn first_non_private<'tcx>( if let Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) = res { continue; } - if (cx.render_options.document_hidden || + if (cx.document_hidden() || !cx.tcx.is_doc_hidden(use_def_id)) && - // We never check for "cx.render_options.document_private" + // We never check for "cx.document_private()" // because if a re-export is not fully public, it's never // documented. cx.tcx.local_visibility(local_use_def_id).is_public() @@ -2628,7 +2628,7 @@ fn get_all_import_attributes<'hir>( attrs = import_attrs.iter().map(|attr| (Cow::Borrowed(attr), Some(def_id))).collect(); first = false; // We don't add attributes of an intermediate re-export if it has `#[doc(hidden)]`. - } else if cx.render_options.document_hidden || !cx.tcx.is_doc_hidden(def_id) { + } else if cx.document_hidden() || !cx.tcx.is_doc_hidden(def_id) { add_without_unwanted_attributes(&mut attrs, import_attrs, is_inline, Some(def_id)); } } @@ -3069,8 +3069,7 @@ fn clean_use_statement_inner<'tcx>( // #[doc(no_inline)] attribute is present. // Don't inline doc(hidden) imports so they can be stripped at a later stage. let mut denied = cx.is_json_output() - || !(visibility.is_public() - || (cx.render_options.document_private && is_visible_from_parent_mod)) + || !(visibility.is_public() || (cx.document_private() && is_visible_from_parent_mod)) || pub_underscore || attrs.iter().any(|a| { a.has_name(sym::doc) diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 44bac8197539b..8b445cd489c1b 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -61,8 +61,6 @@ pub(crate) struct DocContext<'tcx> { // FIXME(eddyb) make this a `ty::TraitRef<'tcx>` set. pub(crate) generated_synthetics: FxHashSet<(Ty<'tcx>, DefId)>, pub(crate) auto_traits: Vec, - /// The options given to rustdoc that could be relevant to a pass. - pub(crate) render_options: RenderOptions, /// This same cache is used throughout rustdoc, including in [`crate::html::render`]. pub(crate) cache: Cache, /// Used by [`clean::inline`] to tell if an item has already been inlined. @@ -138,6 +136,16 @@ impl<'tcx> DocContext<'tcx> { pub(crate) fn is_json_output(&self) -> bool { self.output_format.is_json() && !self.show_coverage } + + /// If `--document-private-items` was passed to rustdoc. + pub(crate) fn document_private(&self) -> bool { + self.cache.document_private + } + + /// If `--document-hidden-items` was passed to rustdoc. + pub(crate) fn document_hidden(&self) -> bool { + self.cache.document_hidden + } } /// Creates a new `DiagCtxt` that can be used to emit warnings and errors. @@ -374,7 +382,6 @@ pub(crate) fn run_global_ctxt( cache: Cache::new(render_options.document_private, render_options.document_hidden), inlined: FxHashSet::default(), output_format, - render_options, show_coverage, }; @@ -411,14 +418,6 @@ pub(crate) fn run_global_ctxt( ); } - // Process all of the crate attributes, extracting plugin metadata along - // with the passes which we are supposed to run. - for attr in krate.module.attrs.lists(sym::doc) { - if attr.is_word() && attr.has_name(sym::document_private_items) { - ctxt.render_options.document_private = true; - } - } - info!("Executing passes"); let mut visited = FxHashMap::default(); @@ -427,9 +426,9 @@ pub(crate) fn run_global_ctxt( for p in passes::defaults(show_coverage) { let run = match p.condition { Always => true, - WhenDocumentPrivate => ctxt.render_options.document_private, - WhenNotDocumentPrivate => !ctxt.render_options.document_private, - WhenNotDocumentHidden => !ctxt.render_options.document_hidden, + WhenDocumentPrivate => ctxt.document_private(), + WhenNotDocumentPrivate => !ctxt.document_private(), + WhenNotDocumentHidden => !ctxt.document_hidden(), }; if run { debug!("running pass {}", p.pass.name); @@ -447,7 +446,8 @@ pub(crate) fn run_global_ctxt( tcx.sess.time("check_lint_expectations", || tcx.check_expectations(Some(sym::rustdoc))); - krate = tcx.sess.time("create_format_cache", || Cache::populate(&mut ctxt, krate)); + krate = + tcx.sess.time("create_format_cache", || Cache::populate(&mut ctxt, krate, &render_options)); let mut collector = LinkCollector { cx: &mut ctxt, visited_links: visited, ambiguous_links: ambiguous }; @@ -455,7 +455,7 @@ pub(crate) fn run_global_ctxt( tcx.dcx().abort_if_errors(); - (krate, ctxt.render_options, ctxt.cache, expanded_macros) + (krate, render_options, ctxt.cache, expanded_macros) } /// Due to , diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 5e5592269af60..56f10b03d62de 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -10,6 +10,7 @@ use tracing::debug; use crate::clean::types::ExternalLocation; use crate::clean::{self, ExternalCrate, ItemId, PrimitiveType}; +use crate::config::RenderOptions; use crate::core::DocContext; use crate::fold::DocFolder; use crate::formats::Impl; @@ -156,7 +157,11 @@ impl Cache { /// Populates the `Cache` with more data. The returned `Crate` will be missing some data that was /// in `krate` due to the data being moved into the `Cache`. - pub(crate) fn populate(cx: &mut DocContext<'_>, mut krate: clean::Crate) -> clean::Crate { + pub(crate) fn populate( + cx: &mut DocContext<'_>, + mut krate: clean::Crate, + render_options: &RenderOptions, + ) -> clean::Crate { let tcx = cx.tcx; // Crawl the crate to build various caches used for the output @@ -164,7 +169,6 @@ impl Cache { assert!(cx.external_traits.is_empty()); cx.cache.traits = mem::take(&mut krate.external_traits); - let render_options = &cx.render_options; let extern_url_takes_precedence = render_options.extern_html_root_takes_precedence; let dst = &render_options.output; diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs index e0ea760cf3ba5..39116061f4854 100644 --- a/src/librustdoc/passes/check_doc_test_visibility.rs +++ b/src/librustdoc/passes/check_doc_test_visibility.rs @@ -102,7 +102,7 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) - return false; } - if (!cx.render_options.document_hidden + if (!cx.document_hidden() && (cx.tcx.is_doc_hidden(def_id.to_def_id()) || inherits_doc_hidden(cx.tcx, def_id, None))) || cx.tcx.def_span(def_id.to_def_id()).in_derive_expansion() { diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index d09949e6868d6..35be849f63fce 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -1070,7 +1070,7 @@ fn preprocessed_markdown_links(s: &str) -> Vec { impl LinkCollector<'_, '_> { #[instrument(level = "debug", skip_all)] fn resolve_links(&mut self, item: &Item) { - if !self.cx.render_options.document_private + if !self.cx.document_private() && let Some(def_id) = item.item_id.as_def_id() && let Some(def_id) = def_id.as_local() && !self.cx.tcx.effective_visibilities(()).is_exported(def_id) @@ -2400,7 +2400,7 @@ fn privacy_error(cx: &DocContext<'_>, diag_info: &DiagnosticInfo<'_>, path_str: diag.span_label(sp, "this item is private"); } - let note_msg = if cx.render_options.document_private { + let note_msg = if cx.document_private() { "this link resolves only because you passed `--document-private-items`, but will break without" } else { "this link will resolve properly if you pass `--document-private-items`" diff --git a/src/librustdoc/passes/lint/redundant_explicit_links.rs b/src/librustdoc/passes/lint/redundant_explicit_links.rs index 855b1884cea96..e49f54f6df946 100644 --- a/src/librustdoc/passes/lint/redundant_explicit_links.rs +++ b/src/librustdoc/passes/lint/redundant_explicit_links.rs @@ -46,13 +46,13 @@ fn check_redundant_explicit_link_for_did( return; }; - let is_hidden = !cx.render_options.document_hidden + let is_hidden = !cx.document_hidden() && (item.is_doc_hidden() || inherits_doc_hidden(cx.tcx, local_item_id, None)); if is_hidden { return; } - let is_private = !cx.render_options.document_private - && !cx.cache.effective_visibilities.is_directly_public(cx.tcx, did); + let is_private = + !cx.document_private() && !cx.cache.effective_visibilities.is_directly_public(cx.tcx, did); if is_private { return; } diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs index 525d05b6a9860..27065d7675bb7 100644 --- a/src/librustdoc/passes/strip_hidden.rs +++ b/src/librustdoc/passes/strip_hidden.rs @@ -43,8 +43,8 @@ pub(crate) fn strip_hidden(krate: clean::Crate, cx: &mut DocContext<'_>) -> clea retained: &retained, cache: &cx.cache, is_json_output, - document_private: cx.render_options.document_private, - document_hidden: cx.render_options.document_hidden, + document_private: cx.document_private(), + document_hidden: cx.document_hidden(), }; stripper.fold_crate(krate) } diff --git a/src/librustdoc/passes/strip_priv_imports.rs b/src/librustdoc/passes/strip_priv_imports.rs index b9b2431f06f2b..a169797e00b2a 100644 --- a/src/librustdoc/passes/strip_priv_imports.rs +++ b/src/librustdoc/passes/strip_priv_imports.rs @@ -14,10 +14,6 @@ pub(crate) const STRIP_PRIV_IMPORTS: Pass = Pass { pub(crate) fn strip_priv_imports(krate: clean::Crate, cx: &mut DocContext<'_>) -> clean::Crate { let is_json_output = cx.is_json_output(); - ImportStripper { - tcx: cx.tcx, - is_json_output, - document_hidden: cx.render_options.document_hidden, - } - .fold_crate(krate) + ImportStripper { tcx: cx.tcx, is_json_output, document_hidden: cx.document_hidden() } + .fold_crate(krate) } diff --git a/src/librustdoc/passes/strip_private.rs b/src/librustdoc/passes/strip_private.rs index 1bd8a7838ec08..045bf0c0be029 100644 --- a/src/librustdoc/passes/strip_private.rs +++ b/src/librustdoc/passes/strip_private.rs @@ -29,12 +29,9 @@ pub(crate) fn strip_private(mut krate: clean::Crate, cx: &mut DocContext<'_>) -> is_json_output, tcx: cx.tcx, }; - krate = ImportStripper { - tcx: cx.tcx, - is_json_output, - document_hidden: cx.render_options.document_hidden, - } - .fold_crate(stripper.fold_crate(krate)); + krate = + ImportStripper { tcx: cx.tcx, is_json_output, document_hidden: cx.document_hidden() } + .fold_crate(stripper.fold_crate(krate)); } // strip all impls referencing private items @@ -43,8 +40,8 @@ pub(crate) fn strip_private(mut krate: clean::Crate, cx: &mut DocContext<'_>) -> retained: &retained, cache: &cx.cache, is_json_output, - document_private: cx.render_options.document_private, - document_hidden: cx.render_options.document_hidden, + document_private: cx.document_private(), + document_hidden: cx.document_hidden(), }; stripper.fold_crate(krate) } diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index dc9889cec2193..51b2821eb1e5f 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -243,7 +243,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { return false; }; - let document_hidden = self.cx.render_options.document_hidden; + let document_hidden = self.cx.document_hidden(); let use_attrs = tcx.hir_attrs(tcx.local_def_id_to_hir_id(def_id)); // Don't inline `doc(hidden)` imports so they can be stripped at a later stage. let is_no_inline = hir_attr_lists(use_attrs, sym::doc).has_word(sym::no_inline) @@ -351,7 +351,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { import_def_id: LocalDefId, target_def_id: LocalDefId, ) -> bool { - if self.cx.render_options.document_hidden { + if self.cx.document_hidden() { return true; } let tcx = self.cx.tcx; diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs index 369fc52860ee2..297485659fa14 100644 --- a/src/librustdoc/visit_lib.rs +++ b/src/librustdoc/visit_lib.rs @@ -30,11 +30,12 @@ impl RustdocEffectiveVisibilities { pub(crate) fn lib_embargo_visit_item(cx: &mut DocContext<'_>, def_id: DefId) { assert!(!def_id.is_local()); + let document_hidden = cx.document_hidden(); LibEmbargoVisitor { tcx: cx.tcx, extern_public: &mut cx.cache.effective_visibilities.extern_public, visited_mods: Default::default(), - document_hidden: cx.render_options.document_hidden, + document_hidden, } .visit_item(def_id) }