Repository navigation
Enable --generate-link-to-definition rustdoc option on std docs
#162808
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
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
800ff08
Enable `--generate-link-to-definition` rustdoc option on std docs
GuillaumeGomez f6db3da
Create new builtin rustc macro `rustdoc_skip_body` and replace the `s…
GuillaumeGomez 4d2c7ad
Disable `unused_macros` check on `rustdoc_skip_body`
GuillaumeGomez b8a7bef
Ignore more std functions body
GuillaumeGomez 6623b95
Stop using `Path` on Windows to generate URLs because of wrong `\` pa…
GuillaumeGomez File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,93 @@ | ||
| //! The expansion from a function when the code would not compile with rustdoc: so if `cfg(doc)`, | ||
| //! expands to a `loop {}`. | ||
|
|
||
| use rustc_ast::token::{self, Delimiter, IdentKind}; | ||
| use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree}; | ||
| use rustc_ast::{ | ||
| AssocItemKind, AttrArgs, AttrItem, Attribute, DelimArgs, ExprKind, Fn, ItemKind, MetaItem, | ||
| Safety, | ||
| }; | ||
| use rustc_expand::base::*; | ||
| use rustc_span::{Ident, Span, sym}; | ||
| use thin_vec::ThinVec; | ||
|
|
||
| pub(crate) fn expand( | ||
| cx: &mut ExtCtxt<'_>, | ||
| attr_path_sp: Span, | ||
| meta_item: &MetaItem, | ||
| mut item: Annotatable, | ||
| ) -> Vec<Annotatable> { | ||
| if !meta_item.is_word() { | ||
| cx.dcx().struct_span_err(attr_path_sp, "`rustdoc_skip_body` doesn't take arguments").emit(); | ||
| } | ||
| let mut is_expected_item = false; | ||
| match item { | ||
| Annotatable::Item(ref mut item) => { | ||
| if let ItemKind::Fn(ref mut fn_) = item.kind { | ||
| expand_macro(cx, attr_path_sp, fn_); | ||
| is_expected_item = true; | ||
| } | ||
| } | ||
| Annotatable::AssocItem(ref mut item, _) => { | ||
| if let AssocItemKind::Fn(ref mut fn_) = item.kind { | ||
| expand_macro(cx, attr_path_sp, fn_); | ||
| is_expected_item = true; | ||
| } | ||
| } | ||
| _ => {} | ||
| } | ||
| if !is_expected_item { | ||
| cx.dcx() | ||
| .struct_span_err(attr_path_sp, "`rustdoc_skip_body` can only be used on functions") | ||
| .emit(); | ||
| } | ||
| vec![item] | ||
| } | ||
|
|
||
| fn cfg_not_doc(cx: &mut ExtCtxt<'_>, sp: Span) -> Attribute { | ||
| // `not(doc)` | ||
| let not_doc = TokenStream::new(vec![ | ||
| TokenTree::token_alone(token::Ident(sym::not, IdentKind::Normal), sp), | ||
| TokenTree::Delimited( | ||
| DelimSpan::from_single(sp), | ||
| DelimSpacing::new(Spacing::JointHidden, Spacing::Alone), | ||
| Delimiter::Parenthesis, | ||
| TokenStream::token_alone(token::Ident(sym::doc, IdentKind::Normal), sp), | ||
| ), | ||
| ]); | ||
|
|
||
| cx.attr_nested( | ||
| AttrItem { | ||
| unsafety: Safety::Default, | ||
| path: cx.path_ident(sp, Ident::new(sym::cfg, sp)), | ||
| args: AttrArgs::Delimited(DelimArgs { | ||
| dspan: DelimSpan::from_single(sp), | ||
| delim: Delimiter::Parenthesis, | ||
| tokens: not_doc, | ||
| }), | ||
| span: sp, | ||
| }, | ||
| sp, | ||
| ) | ||
| } | ||
|
|
||
| fn expand_macro(cx: &mut ExtCtxt<'_>, sp: Span, fn_: &mut Fn) { | ||
| let Some(old_body) = fn_.body.take() else { | ||
| // No body... Well, no possibility to not compile I guess so all good. | ||
| return; | ||
| }; | ||
| let mut old_body = cx.expr_block(old_body); | ||
| // We add on the function's body `#[cfg(not(doc))]`. | ||
| old_body.attrs.push(cfg_not_doc(cx, sp)); | ||
|
|
||
| // We create the `#[cfg(doc)] loop {}` "block". | ||
| let mut loop_expr = cx.expr(sp, ExprKind::Loop(cx.block(sp, ThinVec::new()), None, sp)); | ||
| loop_expr.attrs.push(cx.attr_nested_word(sym::cfg, sym::doc, sp)); | ||
|
|
||
| let mut stmts = ThinVec::new(); | ||
| stmts.push(cx.stmt_expr(loop_expr)); | ||
| stmts.push(cx.stmt_expr(old_body)); | ||
|
|
||
| // We create a new function body containing both blocks. | ||
| fn_.body = Some(cx.block(sp, stmts)); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -461,3 +461,17 @@ macro_rules! hash_map { | |||||||||||||||||||||||||||||||||||||
| map | ||||||||||||||||||||||||||||||||||||||
| }} | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| /// Attribute macro to replace a function's body with `loop {}` under rustdoc. | ||||||||||||||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||||||||||||||
| /// This allows target-specific functions to be documented on other targets, | ||||||||||||||||||||||||||||||||||||||
| /// even when their bodies reference items unavailable on the target used to | ||||||||||||||||||||||||||||||||||||||
| /// build the documentation. Use this with `#[cfg(any(doc, ...))]` to include | ||||||||||||||||||||||||||||||||||||||
| /// such functions in documentation builds. | ||||||||||||||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||||||||||||||
| /// The function's signature must still be valid on the documentation target. | ||||||||||||||||||||||||||||||||||||||
| #[rustc_builtin_macro] | ||||||||||||||||||||||||||||||||||||||
| #[allow(unused_macros)] | ||||||||||||||||||||||||||||||||||||||
| pub(crate) macro rustdoc_skip_body($item:item) { | ||||||||||||||||||||||||||||||||||||||
| /* compiler built-in */ | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+464
to
+477
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Also, I think |
||||||||||||||||||||||||||||||||||||||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"everybody loops" returns?
View changes since the review
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I understand the question so I'll answer to "Is it an issue to use this attribute macro if the function returns something other than
()". Answer:loopreturns!, so it covers every types. It's a little trick we used at some point in rustdoc to remove function bodies (before we realized you could haveimplinside any block).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was referring to the old everybody loops pass that rustdoc used to have, but then removed because it broke with RPIT. Seems like we have pretty much gone full circle except now you have to opt-in to the loop replacement instead.