diff --git a/src/librustdoc/clean/types/tests.rs b/src/librustdoc/clean/types/tests.rs index 9499507b2c0f9..9211cf8050d8b 100644 --- a/src/librustdoc/clean/types/tests.rs +++ b/src/librustdoc/clean/types/tests.rs @@ -72,7 +72,7 @@ fn should_not_trim() { fn is_same_generic() { use crate::clean::types::{PrimitiveType, Type}; use crate::formats::cache::Cache; - let cache = Cache::new(false, false); + let cache = Cache::new(false, false, false, false); let generic = Type::Generic(rustc_span::symbol::sym::Any); let unit = Type::Primitive(PrimitiveType::Unit); assert!(!generic.is_doc_subtype_of(&unit, &cache)); diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 5d16dff24c69a..517fa978dbfbb 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -272,6 +272,10 @@ pub(crate) struct RenderOptions { pub(crate) document_private: bool, /// Document items that have `doc(hidden)`. pub(crate) document_hidden: bool, + /// Hide items marked deprecated from listings, but pages and links still generated. + pub(crate) hide_deprecated: bool, + /// Hide items marked unstable from listings, but pages and links still generated. + pub(crate) hide_unstable: bool, /// If `true`, generate a JSON file in the crate folder instead of HTML redirection files. pub(crate) generate_redirect_map: bool, /// Show the memory layout of types in the docs. @@ -788,6 +792,8 @@ impl Options { let test_runtool_args = matches.opt_strs("test-runtool-arg"); let document_private = matches.opt_present("document-private-items"); let document_hidden = matches.opt_present("document-hidden-items"); + let hide_deprecated = matches.opt_present("hide-deprecated-items"); + let hide_unstable = matches.opt_present("hide-unstable-options"); let run_check = matches.opt_present("check"); let generate_redirect_map = matches.opt_present("generate-redirect-map"); let show_type_layout = matches.opt_present("show-type-layout"); @@ -888,6 +894,8 @@ impl Options { markdown_playground_url, document_private, document_hidden, + hide_deprecated, + hide_unstable, generate_redirect_map, show_type_layout, unstable_features, diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 6e70f5b41c426..5fdc255c616bb 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -384,7 +384,12 @@ pub(crate) fn run_global_ctxt( impl_trait_bounds: Default::default(), generated_synthetics: Default::default(), auto_traits, - cache: Cache::new(render_options.document_private, render_options.document_hidden), + cache: Cache::new( + render_options.document_private, + render_options.document_hidden, + render_options.hide_deprecated, + render_options.hide_unstable, + ), inlined: FxHashSet::default(), output_format, show_coverage, diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 56f10b03d62de..936491d5cbb9e 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -93,6 +93,10 @@ pub(crate) struct Cache { /// Whether to document hidden items. /// This is stored in `Cache` so it doesn't need to be passed through all rustdoc functions. pub(crate) document_hidden: bool, + /// Whether to hide items explicitly marked `#[deprecated]` from listings. + pub(crate) hide_deprecated: bool, + /// Whether to hide items that are unstable from listings. + pub(crate) hide_unstable: bool, /// Crates marked with [`#[doc(masked)]`][doc_masked]. /// @@ -143,8 +147,19 @@ struct CacheBuilder<'a, 'tcx> { } impl Cache { - pub(crate) fn new(document_private: bool, document_hidden: bool) -> Self { - Cache { document_private, document_hidden, ..Cache::default() } + pub(crate) fn new( + document_private: bool, + document_hidden: bool, + hide_deprecated: bool, + hide_unstable: bool, + ) -> Self { + Cache { + document_private, + document_hidden, + hide_deprecated, + hide_unstable, + ..Cache::default() + } } fn parent_stack_last_impl_and_trait_id(&self) -> (Option, Option) { diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index e42997d5b4a14..564f9f82a9986 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -313,11 +313,25 @@ impl<'tcx> Context<'tcx> { let mut map: BTreeMap<_, Vec<_>> = BTreeMap::new(); let mut inserted: FxHashMap> = FxHashMap::default(); + let hide_deprecated = self.shared.cache.hide_deprecated; + let hide_unstable = self.shared.cache.hide_unstable; + let tcx = self.tcx(); + for item in &m.items { if item.is_stripped() { continue; } + let is_deprecated = item.deprecation(tcx).is_some(); + let is_unstable = item + .stability(tcx) + .is_some_and(|s| s.is_unstable() && s.feature != sym::rustc_private); + + if (hide_deprecated && is_deprecated) || (hide_unstable && is_unstable) { + // Hide deprecated/unstable items from sidebar listings. + continue; + } + let short = item.type_(); let myname = match item.name { None => continue, @@ -866,7 +880,16 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { self.shared.fs.write(joint_dst, buf)?; if !self.info.render_redirect_pages { - self.shared.all.borrow_mut().append(full_path(self, item), &item_type); + let hide_deprecated = self.shared.cache.hide_deprecated; + let hide_unstable = self.shared.cache.hide_unstable; + let tcx = self.tcx(); + let is_deprecated = item.deprecation(tcx).is_some(); + let is_unstable = item + .stability(tcx) + .is_some_and(|s| s.is_unstable() && s.feature != sym::rustc_private); + if !(hide_deprecated && is_deprecated) && !(hide_unstable && is_unstable) { + self.shared.all.borrow_mut().append(full_path(self, item), &item_type); + } } // If the item is a macro, redirect from the old macro URL (with !) // to the new one (without). diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 8740b5935973c..7c47a4a52fd79 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1584,6 +1584,10 @@ fn render_deref_methods( } fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) -> bool { + if item.deprecation(tcx).is_some() { + return false; + } + let self_type_opt = match item.kind { clean::MethodItem(ref method, _) => method.decl.receiver_type(), clean::RequiredMethodItem(ref method) => method.decl.receiver_type(), @@ -1787,6 +1791,18 @@ fn render_impl( } }; + // Skip deprecated/unstable associated items when flags are enabled. + let hide_deprecated = cx.shared.cache.hide_deprecated; + let hide_unstable = cx.shared.cache.hide_unstable; + let tcx = cx.tcx(); + let is_deprecated = item.deprecation(tcx).is_some(); + let is_unstable = item + .stability(tcx) + .is_some_and(|s| s.is_unstable() && s.feature != sym::rustc_private); + if (hide_deprecated && is_deprecated) || (hide_unstable && is_unstable) { + return Ok(()); + } + let in_trait_class = if trait_.is_some() { " trait-impl" } else { "" }; let mut doc_buffer = String::new(); diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 0c511738d7c8a..0a4f38b4a4c8f 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -412,6 +412,45 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i )?; for (_, myitem) in ¬_stripped_items[&type_] { + // Skip deprecated/unstable items in module listings when the flags are enabled. + let hide_deprecated = cx.shared.cache.hide_deprecated; + let hide_unstable = cx.shared.cache.hide_unstable; + + // Direct attributes on the item + let is_deprecated_item = myitem.deprecation(tcx).is_some(); + let is_unstable_item = myitem + .stability(tcx) + .is_some_and(|s| s.is_unstable() && s.feature != sym::rustc_private); + + // Reexports/imports/extern crate metadata + let (is_deprecated_reexport, is_unstable_reexport) = match myitem.kind { + clean::ImportItem(ref import) => { + if let Some(import_def_id) = import.source.did { + let depr = tcx.lookup_deprecation(import_def_id).is_some(); + let unst = tcx.lookup_stability(import_def_id).is_some_and(|s| { + s.is_unstable() && s.feature != sym::rustc_private + }); + (depr, unst) + } else { + (false, false) + } + } + clean::ExternCrateItem { .. } => { + let def_id = myitem.item_id.expect_def_id(); + let depr = tcx.lookup_deprecation(def_id).is_some(); + let unst = tcx + .lookup_stability(def_id) + .is_some_and(|s| s.is_unstable() && s.feature != sym::rustc_private); + (depr, unst) + } + _ => (false, false), + }; + + if (hide_deprecated && (is_deprecated_item || is_deprecated_reexport)) + || (hide_unstable && (is_unstable_item || is_unstable_reexport)) + { + continue; + } match myitem.kind { clean::ExternCrateItem { ref src } => { use crate::html::format::print_anchor; diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index e4601bfb20d7d..3c5c52246e788 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -254,6 +254,22 @@ fn opts() -> Vec { "document items that have doc(hidden)", "", ), + opt( + Unstable, + FlagMulti, + "", + "hide-deprecated-items", + "Hide items marked deprecated from listings, but pages and links still generated.", + "", + ), + opt( + Unstable, + FlagMulti, + "", + "hide-unstable-options", + "Hide items marked unstable from listings, but pages and links still generated.", + "", + ), opt(Stable, FlagMulti, "", "test", "run code examples as tests", ""), opt(Stable, Multi, "", "test-args", "arguments to pass to the test runner", "ARGS"), opt( diff --git a/tests/run-make/rustdoc-default-output/output-default.stdout b/tests/run-make/rustdoc-default-output/output-default.stdout index 49eaf7e2e1e0e..be611fabe61a4 100644 --- a/tests/run-make/rustdoc-default-output/output-default.stdout +++ b/tests/run-make/rustdoc-default-output/output-default.stdout @@ -33,6 +33,12 @@ Options: document private items --document-hidden-items document items that have doc(hidden) + --hide-deprecated-items + Hide items marked deprecated from listings, but pages + and links still generated. + --hide-unstable-options + Hide items marked unstable from listings, but pages + and links still generated. --test run code examples as tests --test-args ARGS arguments to pass to the test runner