Skip to content

[rustdoc] Add support new bang macro kinds #145458

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

GuillaumeGomez
Copy link
Member

@GuillaumeGomez GuillaumeGomez commented Aug 15, 2025

This implements #145153 in rustdoc. This PR voluntarily doesn't touch anything related to intra-doc links, I'll send a follow-up if needed.

So now about the implementation itself: this is a weird case where a macro can be different things at once but still only gets one file generated. I saw two ways to implement this:

  1. Handle ItemKind::Macro differently and iter through its MacroKinds values.
  2. Add new placeholder variants in the ItemKind enum, which means that when we encounter them in rendering, we need to ignore them. It also makes the ItemKind enum bigger (and also needs more code to be handled). Another downside is that it needs to be handled in the JSON output.

I implemented 1. in the first commit and 2. in the third commit so if we don't to keep 2., I can simply remove it. I personally have no preference for one or the other since the first is "simpler" but it's easy to forget to go through the macro kinds whereas the second needs a lot more code.

Now there was an interesting improvement that came with this PR in the html::render::print_item::item_module function: I simplified its implementation and split the different parts in a HashMap where the key is the item type. So then, we can just iterate through the keys and open/close the section at each iteration instead of keeping an Option<section> around.

cc @joshtriplett

@rustbot
Copy link
Collaborator

rustbot commented Aug 15, 2025

r? @notriddle

rustbot has assigned @notriddle.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added A-rustdoc-json Area: Rustdoc JSON backend 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 Aug 15, 2025
@rustbot
Copy link
Collaborator

rustbot commented Aug 15, 2025

Some changes occurred in HTML/CSS/JS.

cc @GuillaumeGomez, @jsha, @lolbinarycat

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.

I can't really say much about the actual logic correctness (it seems mostly fine?), but i do have a few nitpicks about naming, datatype structure and logic clarity.

It was also a bit weird reviewing this with the two alternate implementations, since as far as I can tell there's a few lines of code that are common between both impls, but actually have different semantics between them.

@@ -163,6 +164,27 @@ impl SharedContext<'_> {
}
}

struct SidebarItem {
name: String,
is_actually_macro: bool,
Copy link
Contributor

Choose a reason for hiding this comment

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

Unclear what "actually" means here, is it possible for a sidebar item to be a macro, but not actually be a macro?

I think this should probably be renamed to is_decl_macro or is_macro_rules, or maybe is_macro_placeholder?

Comment on lines +619 to +625
for (const item of filtered) {
let name = item;
let isMacro = false;
if (Array.isArray(item)) {
name = item[0];
isMacro = true;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I believe Window.SIDEBAR_ITEMS in rustdoc.d.ts should now have type { [key: string]: (string | [string, 1])[] }, and the previous @ts-expect-error should be able to be converted to a nonnull call?

source: display_macro_source(cx, name, macro_def),
macro_rules: macro_def.macro_rules,
},
None,
Copy link
Contributor

Choose a reason for hiding this comment

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

Why None and not just MacroKinds::BANG ?

@@ -924,7 +942,7 @@ pub(crate) enum ItemKind {
ForeignStaticItem(Static, hir::Safety),
/// `type`s from an extern block
ForeignTypeItem,
MacroItem(Macro),
MacroItem(Macro, Option<MacroKinds>),
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't like the use of Option here, for two reasons:

  1. MacroKinds::empty() already can represent the absence of any value
  2. what None actually represents here is MacroKinds::BANG

I think the rationale for the second is that this represents extra macro kinds, but I think the use of Option is still unnecessary, as it leaves MacroKinds::empty() as a meaningless value that should never be used, which seems like something we would want to avoid.

Comment on lines +940 to +941
AttrMacroItem,
DeriveMacroItem,
Copy link
Contributor

Choose a reason for hiding this comment

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

I feel like these should at the very least have a doc comment saying these are for non-proc macros.

Comment on lines +422 to +423
let tag =
if section_id == "reexports" { REEXPORTS_TABLE_OPEN } else { ITEM_TABLE_OPEN };
Copy link
Contributor

Choose a reason for hiding this comment

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

We have an ItemSection as my_section, please compare that with ItemSection::Reexport instead of doing typo-prone (and possibly slower) string comparison.

Comment on lines +98 to +101
// Is this a good idea?
clean::AttrMacroItem => ItemType::ProcAttribute,
// Is this a good idea?
clean::DeriveMacroItem => ItemType::ProcDerive,
Copy link
Contributor

Choose a reason for hiding this comment

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

It seems fairly confusing to me, I don't see the advantage (is it so item_module groups things correctly? if that's the case, then the first commit on its own would not be correct, since it would categorize these macros as ItemType::Macro), and it already causes a bit of weirdness in html_filename which would not be needed if these were categorized as Macro instead.

if we did want to make this change, I would at least want to change the names of the item types to not imply they must be derives.

MacroItem(m) => ItemEnum::Macro(m.source.clone()),
MacroItem(m, _) => ItemEnum::Macro(m.source.clone()),
// They are just placeholders so no need to handle them.
AttrMacroItem | DeriveMacroItem => return None,
Copy link
Member

Choose a reason for hiding this comment

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

We should handle these like KeywordItem, and return None from them earlier, so that from_clean_item can remain a total function (and not return an Option).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-rustdoc-json Area: Rustdoc JSON backend 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.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants