Skip to content

Conversation

@GuillaumeGomez
Copy link
Member

This PR adds a new JS setting which allows the JS to hide deprecated items. This is especially useful for crates like std which accumulates deprecated items but never removes them.

Nicely enough, the "deprecation" information was already in the search index, meaning I didn't need to change anything there. Before this PR, it was only used to make the deprecated items rank lower. Well now it's also used to generate an extra CSS class, allowing the JS setting to work.

This is taking over #149551.

This feature got approved by the rustdoc team in the meeting of december.

You can give it a try here.

r? @lolbinarycat

@rustbot
Copy link
Collaborator

rustbot commented Jan 13, 2026

Some changes occurred in HTML/CSS/JS.

cc @lolbinarycat

@rustbot rustbot added A-rustdoc-json Area: Rustdoc JSON backend A-rustdoc-search Area: Rustdoc's search feature S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue. T-rustdoc-frontend Relevant to the rustdoc-frontend team, which will review and decide on the web UI/UX output. labels Jan 13, 2026
@rust-log-analyzer

This comment has been minimized.

@GuillaumeGomez GuillaumeGomez force-pushed the hide-deprecated-items branch 2 times, most recently from 1fe45dd to 4622f64 Compare January 14, 2026 13:54
@rustbot rustbot added the A-rustdoc-js Area: Rustdoc's JS front-end label Jan 14, 2026
@rustbot

This comment has been minimized.

1 similar comment
@rustbot

This comment has been minimized.

@GuillaumeGomez
Copy link
Member Author

Rebased so it includes #151053, which hopefully should fix the flakyness issue.

@lolbinarycat lolbinarycat added the relnotes Marks issues that should be documented in the release notes of the next release. label Jan 14, 2026
@lolbinarycat
Copy link
Contributor

This made me realize that we use the word "hide" inconsistently in this settings panel, sometimes we mean "collapse, with a button to expand it again", and sometimes we mean "act like it doesn't exist at all".

I think the former should be referred to with the verb "Collapse", I think that would make things seem a bit less inconsistent.

Copy link
Contributor

@lolbinarycat lolbinarycat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Logic looks sound, but there's a bunch of stuff that I think could be written either more readably or more compactly, and there's a few more test cases I would like to see.

View changes since this review

Either::Right(boring)
};

let mut deprecation_attr = if trait_item_deprecated || item.is_deprecated(cx.tcx()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let mut deprecation_attr = if trait_item_deprecated || item.is_deprecated(cx.tcx()) {
let mut deprecation_class = if trait_item_deprecated || item.is_deprecated(cx.tcx()) {

This isn't a full attribute, only the value of the class attribute.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also makes it clear we aren't talking about the #[deprecation] (rust) attribute, but an html attribute.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, updating variable name then.

}

fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> impl fmt::Display {
fn deprecation_class(is_deprecated: bool) -> &'static str {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
fn deprecation_class(is_deprecated: bool) -> &'static str {
fn deprecation_class_attr(is_deprecated: bool) -> &'static str {

This is a full attribute.


let content = document_full(m, cx, HeadingOffset::H5).to_string();

let mut deprecation_attr =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let mut deprecation_attr =
let mut deprecation_class =

same nit as before, not a full attribute.

Comment on lines 319 to 339
if (getSettingValue("source-sidebar-show") === "true") {
addClass(document.documentElement, "src-sidebar-expanded");
}
if (getSettingValue("hide-sidebar") === "true") {
addClass(document.documentElement, "hide-sidebar");
}
if (getSettingValue("hide-toc") === "true") {
addClass(document.documentElement, "hide-toc");
}
if (getSettingValue("hide-modnav") === "true") {
addClass(document.documentElement, "hide-modnav");
}
if (getSettingValue("sans-serif-fonts") === "true") {
addClass(document.documentElement, "sans-serif");
}
if (getSettingValue("word-wrap-source-code") === "true") {
addClass(document.documentElement, "word-wrap-source-code");
}
if (getSettingValue("hide-deprecated-items") === "true") {
addClass(document.documentElement, "hide-deprecated-items");
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is starting to look like a lot of duplicated code that could be made more compact by just calling into changeSetting, or by taking advantage of the fact most of the class names and the settings names are the same. Is there a reason this isn't done?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I was thinking about it. Well, since you agree, I can simplify this code. :)

Comment on lines 81 to 56
case "hide-deprecated-items":
if (value === true) {
addClass(document.documentElement, "hide-deprecated-items");
} else {
removeClass(document.documentElement, "hide-deprecated-items");
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would think this could all be done much more compactly by having a single case body for all the settings that add/remove a class of the same name, no? like, addClass(document.documentElement, settingName); (and the same for removeClass) should handle the majority of settings, right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as previous comment. In short: strongly agree.

Comment on lines +373 to +376
#[deprecated(since = "1.26.0", note = "deprecated")]
pub struct DeprecatedStruct;

pub struct NonDeprecatedStruct;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should have a since = "future" deprecation notice, and make sure that works correctly both in the regular module view and in rustdoc search (i'm not sure, but there's a chance future deprecations are actually treated differently between the two)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I use is_in_effect, so it won't impact the display, adding a case though.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad, it is impacted. ^^'

Comment on lines 39 to 42
// We disable the setting.
click: "#hide-deprecated-items"
// All of them should be displayed back.
wait-for-css: ("details.deprecated", {"display": "block"}, ALL)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just to make sure localStorage is working, one of these times we should keep the setting checked, go to a different page, make sure all the deprecated items are hidden, uncheck it, then make sure all the deprecated items are shown.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Local storage is a bit tricky locally as it depends on the web browser whether or not the local storage is shared per-file or per-folder. So I'd rather not check that if you don't mind.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, right. file://// is weird. one of these days it would be nice to also have some test ran against a normal http server, so we can test stuff like localstorage.

// and so do file:/// URLs, which means we need to block
// it here if we want to avoid breaking the main docs site.
// https://github.com/rust-lang/rust/issues/145646
block-network-request: "file://*//*"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this happening here an not literally anywhere else (genuine question)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's because we try to load JS files which don't exist. As for the why, might be worth asking @notriddle and to update this comment.

@lolbinarycat
Copy link
Contributor

@rustbot author

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 14, 2026
@rustbot
Copy link
Collaborator

rustbot commented Jan 14, 2026

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@GuillaumeGomez
Copy link
Member Author

@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jan 16, 2026
Copy link
Contributor

@lolbinarycat lolbinarycat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code looks much better (better than what I would've written, even), but I'm still not 100% satisfied with the tests.

View changes since this review

@@ -64,7 +64,7 @@ xmlns="http://www.w3.org/2000/svg" fill="black" height="18px">\
<path d="M3,5h16M3,11h16M3,17h16" stroke-width="2.75"/></svg>');
}

:root.sans-serif {
:root.sans-serif-fonts {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good job changing the class name to sans-serif-fonts instead of changing the setting name, it's an elegant solution that simplifies the code without breaking compatibility with existing localStorage.

Comment on lines 401 to 403
#[deprecated(since = "future", note = "deprecated")]
/// doc
pub fn future_deprecated_fn() {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we put #![staged_api] on this lib so this actually get interpreted as DeprecatedSince::Future, so we can actually have coverage for the use of is_in_effect? Also, I want to see what DeprecatedSince::Future does to the search results, since that attribute is handled with the existing data, and I'm not sure if that uses is_in_effect or not.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neither future nor CURRENT_RUSTC_VERSION work:

error: 'since' must be a Rust version number, such as "1.31.0"
   --> lib.rs:402:9
    |
402 |         #[deprecated(since = "CURRENT_RUSTC_VERSION", note = "deprecated")]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

I think staged_api prevents that. What about in a follow-up?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to look into the attribute parsing code (compiler/rustc_attr_parsing/src/attributes/deprecation.rs), and it looks like the magic string we actually want here is "TBD", not "future", and we shouldn't even need staged_api either. If that doesn't work, then I'd be fine putting it off to a followup.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me check.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep it works! I updated the test.

// with deprecated associated items.
go-to: "file://" + |DOC_PATH| + "/lib2/deprecated/struct.NonDeprecatedStruct.html"

// There should be five deprecated items...
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment doesn't make sense anymore.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed it.

assert-count: ("details.deprecated", 6)
// One of which being a deprecated impl because the trait itself is deprecated.
assert-count: ("details.implementors-toggle.deprecated", 1)
// And another has `since = "future"` and should also be impacted here.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"should also be impacted" is pretty vague.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, improved the comment.

@GuillaumeGomez
Copy link
Member Author

GuillaumeGomez commented Jan 17, 2026

Applied parts of the suggestions.

@lolbinarycat
Copy link
Contributor

One final bit of test coverage I would like to see: when searching future_deprecated_fn with "Hide deprecated items" enabled, it should not be hidden. It's a small thing, but it would be nice to make sure the handling of items with pending deprecation has consistency across search and non-search contexts.

… value in the end, no need to keep it around. Also: takes into account "is_in_effect"
Improve the `perform-search` goml function to work when search is already open
@lolbinarycat
Copy link
Contributor

Thanks!

@bors r+

@rust-bors
Copy link
Contributor

rust-bors bot commented Jan 19, 2026

📌 Commit aef8112 has been approved by lolbinarycat

It is now in the queue for this repository.

@rust-bors rust-bors bot added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-rustdoc-js Area: Rustdoc's JS front-end A-rustdoc-json Area: Rustdoc JSON backend A-rustdoc-search Area: Rustdoc's search feature relnotes Marks issues that should be documented in the release notes of the next release. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue. T-rustdoc-frontend Relevant to the rustdoc-frontend team, which will review and decide on the web UI/UX output.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants