Skip to content

Rustdoc bang attr macro#152449

Open
GuillaumeGomez wants to merge 12 commits intorust-lang:mainfrom
GuillaumeGomez:rustdoc-bang-attr-macro
Open

Rustdoc bang attr macro#152449
GuillaumeGomez wants to merge 12 commits intorust-lang:mainfrom
GuillaumeGomez:rustdoc-bang-attr-macro

Conversation

@GuillaumeGomez
Copy link
Copy Markdown
Member

@GuillaumeGomez GuillaumeGomez commented Feb 10, 2026

View all comments

Since it seems like I can't reopen #145458, opening this one. Although, it's the same PR minus the last new commit to handle a comment that was left unresolved in the original PR. All relevant details are still in the original PR though.

It's an alternative (and likely a take-over) of #148005 since lang-team rejected the idea to add documentation on macro branches, making the multiple files approach less suitable.

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.

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.

From RFCs:

derive:

Screenshot From 2026-04-18 03-11-40

attr:

Screenshot From 2026-04-18 03-11-31

both:

Screenshot From 2026-04-18 03-11-50

r? @notriddle

@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Feb 10, 2026

Some changes occurred in HTML/CSS/JS.

cc @lolbinarycat

@rustbot rustbot added A-rustdoc-js Area: Rustdoc's JS front-end 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 Feb 10, 2026
@rust-log-analyzer

This comment has been minimized.

@GuillaumeGomez GuillaumeGomez force-pushed the rustdoc-bang-attr-macro branch from 20f13be to 4b35c49 Compare February 10, 2026 18:18
@rust-log-analyzer

This comment has been minimized.

@GuillaumeGomez GuillaumeGomez force-pushed the rustdoc-bang-attr-macro branch from 4b35c49 to 4416897 Compare February 10, 2026 20:25
@GuillaumeGomez
Copy link
Copy Markdown
Member Author

Oh and also cc @lolbinarycat as you reviewed the original PR too. :)

@rust-log-analyzer

This comment has been minimized.

@GuillaumeGomez GuillaumeGomez force-pushed the rustdoc-bang-attr-macro branch from 4416897 to be7815f Compare February 10, 2026 20:41
@rust-bors

This comment has been minimized.

@GuillaumeGomez GuillaumeGomez force-pushed the rustdoc-bang-attr-macro branch from be7815f to 3e05767 Compare February 20, 2026 12:05
@rustbot

This comment has been minimized.

@GuillaumeGomez
Copy link
Copy Markdown
Member Author

Fixed merge conflicts.

@rust-bors

This comment has been minimized.

@lolbinarycat
Copy link
Copy Markdown
Contributor

blocking this on #154902, since that relies on bang macro === macro_rules macro.

@GuillaumeGomez GuillaumeGomez force-pushed the rustdoc-bang-attr-macro branch from 3e05767 to ce98d4e Compare April 7, 2026 16:31
@rustbot

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

Comment thread tests/rustdoc-gui/src/test_docs/macros.rs Outdated
@GuillaumeGomez GuillaumeGomez force-pushed the rustdoc-bang-attr-macro branch from ce98d4e to 5ada01c Compare April 7, 2026 22:44
@GuillaumeGomez GuillaumeGomez force-pushed the rustdoc-bang-attr-macro branch from 5ada01c to 26f32d9 Compare April 17, 2026 23:13
@rustbot

This comment has been minimized.

@GuillaumeGomez GuillaumeGomez force-pushed the rustdoc-bang-attr-macro branch 2 times, most recently from eef2a58 to cbe154c Compare April 18, 2026 15:46
@GuillaumeGomez
Copy link
Copy Markdown
Member Author

Ready for review.

Copy link
Copy Markdown
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.

After reading through everything it seems there's still some level of conflation between declarative (macro_rules! and v2 macros) and procedural macros.

I still feel like our data model for macros is a bit of a mess, and there doesn't seem to be a clear vision of what the desired end state is, at least not one I have access to.

The search handling I'm also unsure about the design of. Remember we have itemParents now, that could be useful here.

I also worry about if cross-crate inlining breaks any of this stuff. In general, I think the test coverage is a bit lacking, there are only 7 potential cases1, but not a single test suite covers all of them.

View changes since this review

Footnotes

  1. I guess doubled to 14 if you want to do all of them through cross-crate reexports too

Comment on lines +2909 to +2910
MacroKinds::ATTR => clean_proc_macro(item, &mut name, MacroKind::Attr, cx.tcx),
MacroKinds::DERIVE => clean_proc_macro(item, &mut name, MacroKind::Derive, cx.tcx),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think this is wrong, a macro_rules! macro should be able to go into this branch, which does not seem ideal.

Do we really not have a way of just... checking if something is a proc macro or not? can clean_proc_macro handle being given a non-proc macro?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

In this case, if macro_rules! containing only an attr or a derive, we treat them the same as their proc-macro equivalent.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

is that the desired behavior? it seems somewhat odd.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yep it is. :)

Comment thread src/librustdoc/clean/mod.rs Outdated
Comment thread src/librustdoc/formats/item_type.rs Outdated
Comment on lines +104 to +105
BangMacroAttribute = 28,
BangMacroDerive = 29,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

These feel like misnomers, a "bang macro" generally refers to a fn-like macro, called with !(), not just anything declared with macro_rules!. also could definitely benefit from doc comments.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

It's about how they're declared, not how they're used. Big +1 for the missing docs, adding that.

Copy link
Copy Markdown
Contributor

@lolbinarycat lolbinarycat Apr 24, 2026

Choose a reason for hiding this comment

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

problem is that's not what "bang macro" conventionally means, and i would rather not introduce more instances of "this term is used completely differently within rustdoc".

i would prefer we just use "DeclMaro", as both of these can be grouped under "declarative macros"

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Sounds good to me.

Comment thread src/librustdoc/clean/types.rs Outdated
Comment thread src/librustdoc/clean/utils.rs Outdated
Comment thread src/librustdoc/html/static/js/main.js Outdated
Comment on lines +789 to +797
block("attr", "attributes", "Attribute Macros");
block("attr", "attribute-macros", "Attribute Macros");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Once again, not a fan of bugfixes that break links being buried within a larger change like this.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Needed for tests.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

ah... it might be better to rename the other block, as that should break drastically less links

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

That's a very good point. Switching the change between the two then.

* But the documentation lives in a single `macro.NAME.html` page, and
* this boolean flag is used for generating that HREF.
*/
isBangMacro: boolean,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I really don't like this field name.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Open to suggestions. :)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

the problem is the current semantics are "is this a non-proc macro that is usable in multiple ways or is fn-like"

i think naming it based on purpose rather than on definition would be good, so forceMacroHref.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Sounds good to me!

Comment on lines +1663 to +1669
if (item.ty === 28 || item.ty === 29) {
// "proc attribute" is 23, "proc derive" is 24 whereas "bang macro attribute" is 28 and
// "bang macro derive" is 29, so 5 of difference to go from the latter to the former.
item.ty -= 5;
item.isBangMacro = true;
}
return item;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

ah, so this is the point of adding those two enum variants...

I do wonder if there's a better way to encode this...

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Likely not but very interested if you have ideas.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

we could overload the last field even more x3

Comment thread src/librustdoc/html/static/js/search.js Outdated
let href;
let traitPath = null;
const type = itemTypesName[item.ty];
const type = item.entry && item.entry.isBangMacro ? "macro" : itemTypesName[item.ty];
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

so, these hybrid macros will show up with attr: and derive: searches but will have macro in the url? seems confusing.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

That's the whole debate we had 2 rustdoc meetings ago. The alternative was to have a file for each kind of the macro but this approach was rejected.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

derive and attr are children of macro, so it should be fine.

Comment on lines +6 to +25
/// An attribute bang macro.
#[macro_export]
macro_rules! attr_macro {
attr() () => {};
() => {};
}

/// A derive bang macro.
#[macro_export]
macro_rules! derive_macro {
derive() () => {};
() => {};
}

#[macro_export]
macro_rules! one_for_all_macro {
attr() () => {};
derive() () => {};
() => {};
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

what about something of the shape of:

#[macro_export]
macro_rules! attr_macro {
    attr() () => {};
}

or

#[macro_export]
macro_rules! one_for_all_macro {
    attr() () => {};
    derive() () => {};
}

I suspect the former may show up as a proc macro.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I confirm it would. Adding a test to cover them.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Ah it's already tested in tests/rustdoc-html/macro/macro-attr.rs actually. :)

@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 Apr 22, 2026
@GuillaumeGomez
Copy link
Copy Markdown
Member Author

Went through all comments and pushed improvements and suggestions (and a new test). So if I didn't miss anything, only tests missing are for cross-crate, right?

@rust-log-analyzer

This comment has been minimized.

@GuillaumeGomez GuillaumeGomez force-pushed the rustdoc-bang-attr-macro branch from 6058428 to 76a6846 Compare April 24, 2026 01:26
@GuillaumeGomez
Copy link
Copy Markdown
Member Author

The debug_assert_matches I added were too strict on the matching, so I relaxed them a bit. But still a super good idea. :)

@rust-log-analyzer

This comment has been minimized.

@rust-bors

This comment has been minimized.

@GuillaumeGomez GuillaumeGomez force-pushed the rustdoc-bang-attr-macro branch from 76a6846 to 6eca740 Compare April 27, 2026 15:56
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Apr 27, 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
Copy Markdown
Member Author

Updated ItemType variants name, updated the ID so attribute macros keep attributes and renamed the field.

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 S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. 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.

6 participants