-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Tracking issue: rfc 1990 - add external doc attribute to rustc #44732
Comments
At today's Cargo meeting, and interesting question was raised how Cargo should check if it should rebuild the docs when an external file with docs changes. Here's some info on how dependency-tracking works today: When doing Curiously, TL;DR: |
@matklad So, it sounds like the current behavior is correct but could be made more efficient. That's better than being incorrect. |
There's an edge case where it might not do rebuild when it should, if in #[path="../../bar.rs"]
pub mod bar; Or include!("../../bar.rs") That is, if you touch files outside of the Cargo package directory. Other than that yes, current behavior is correct!. |
Partial implementation of rust-lang/rfcs#1990 (needs error reporting work) cc rust-lang#44732
rustdoc: include external files in documentation (RFC 1990) Part of rust-lang/rfcs#1990 (needs work on the error reporting, which i'm deferring to after this initial PR) cc #44732 Also fixes #42760, because the prep work for the error reporting made it easy to fix that at the same time.
This probably won't cause any issues in the real world, but related to the discussion above about dependency tracking, I noticed that Compare vs.
It looks like rust/src/libsyntax/ext/source_util.rs Line 152 in a0db04b
so presumably doing the same thing inside the implementation of rust/src/libsyntax/ext/expand.rs Line 1117 in 632ad19
|
I neglected to mention, but it looks like there's even a test to ensure that files used in |
Humorously enough, i asked about that when i was writing it:
Judging from the above discussion in this thread, it may be prudent to add it, but it also may not be necessary. I'd defer to @rust-lang/compiler for that, i guess. |
I personally would find it quite unfortunate if changing the included file doesn't lead to rebuilding the code. (One day, incremental compilation should make that a very fast rebuild.) I realize that usually it won't affect the generated code, but I could imagine a syntax extension of some kind processing doc comments (after all documentation has been normalized to the equivalent of a |
The current implementation seems to interact poorly with $ cat test.md
foo
$ cat test.rs
#![doc(include = "test.md")]
#![feature(external_doc)]
#![deny(missing_docs)]
fn main() {}
$ rustc +nightly test.rs
error: missing documentation for crate
--> test.rs:1:1
|
1 | / #![doc(include = "test.md")]
2 | | #![feature(external_doc)]
3 | | #![deny(missing_docs)]
4 | |
5 | | fn main() {}
| |____________^
|
note: lint level defined here
--> test.rs:3:9
|
3 | #![deny(missing_docs)]
| ^^^^^^^^^^^^
error: aborting due to previous error |
@trevyn include_str is not stable, it's still behind a feature gate. |
To be clear, EDIT: clarified |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
…=petrochenkov Stabilize extended_key_value_attributes Closes rust-lang#44732. Closes rust-lang#78835. Closes rust-lang#82768 (by making it irrelevant). # Stabilization report ## Summary This stabilizes using macro expansion in key-value attributes, like so: ```rust #[doc = include_str!("my_doc.md")] struct S; #[path = concat!(env!("OUT_DIR"), "/generated.rs")] mod m; ``` See Petrochenkov's excellent blog post [on internals](https://internals.rust-lang.org/t/macro-expansion-points-in-attributes/11455) for alternatives that were considered and rejected ("why accept no more and no less?") This has been available on nightly since 1.50 with no major issues. ## Notes ### Accepted syntax The parser accepts arbitrary Rust expressions in this position, but any expression other than a macro invocation will ultimately lead to an error because it is not expected by the built-in expression forms (e.g., `#[doc]`). Note that decorators and the like may be able to observe other expression forms. ### Expansion ordering Expansion of macro expressions in "inert" attributes occurs after decorators have executed, analogously to macro expressions appearing in the function body or other parts of decorator input. There is currently no way for decorators to accept macros in key-value position if macro expansion must be performed before the decorator executes (if the macro can simply be copied into the output for later expansion, that can work). ## Test cases - https://github.com/rust-lang/rust/blob/master/src/test/ui/attributes/key-value-expansion-on-mac.rs - https://github.com/rust-lang/rust/blob/master/src/test/rustdoc/external-doc.rs The feature has also been dogfooded extensively in the compiler and standard library: - rust-lang#83329 - rust-lang#83230 - rust-lang#82641 - rust-lang#80534 ## Implementation history - Initial proposal: rust-lang#55414 (comment) - Experiment to see how much code it would break: rust-lang#67121 - Preliminary work to restrict expansion that would conflict with this feature: rust-lang#77271 - Initial implementation: rust-lang#78837 - Fix for an ICE: rust-lang#80563 ## Unresolved Questions ~~rust-lang#83366 (comment) listed some concerns, but they have been resolved as of this final report.~~ ## Additional Information There are two workarounds that have a similar effect for `#[doc]` attributes on nightly. One is to emulate this behavior by using a limited version of this feature that was stabilized for historical reasons: ```rust macro_rules! forward_inner_docs { ($e:expr => $i:item) => { #[doc = $e] $i }; } forward_inner_docs!(include_str!("lib.rs") => struct S {}); ``` This also works for other attributes (like `#[path = concat!(...)]`). The other is to use `doc(include)`: ```rust #![feature(external_doc)] #[doc(include = "lib.rs")] struct S {} ``` The first works, but is non-trivial for people to discover, and difficult to read and maintain. The second is a strange special-case for a particular use of the macro. This generalizes it to work for any use case, not just including files. I plan to remove `doc(include)` when this is stabilized (rust-lang#82539). The `forward_inner_docs` workaround will still compile without warnings, but I expect it to be used less once it's no longer necessary.
The latest rust nightlies and beta (at stable version 1.55) include a change from #![cfg_attr(feature = "nightly", feature(external_doc))] #![cfg_attr(feature = "nightly", doc(include = "../README.md"))] to removing `feature(external_doc)` and also changing the syntax of the second line to #![cfg_attr(feature = "nightly", doc = include_str!("../README.md"))] However. `include_str!` is stable currently, but the syntax of `doc = ` is expressly disallowed. This gives me four options: 1. Don't build documentation (bad) 2. Copy-pasta README.md into src/lib.rs (also bad) 3. Support only beta/nightly but not stable (completely untennable for a crate with ~14 million downloads) 4. Support only stable but not beta/nightly (also untennable) Further, waiting for this to be "fixed" by its inclusion in stable Rust in about a week means that our MSRV increases from 1.41 to 1.56, with no changes to actual code (other than how to build documentation) at all, which seems quite unfriendly to downstream dependents who are pinning their rust versions for whatever reason. So, sadly, it seems the most friendly fix is to copy-pasta our README.md into the codebase. (cf. rust-lang/rust#44732, rust-lang/rust#82539)
The latest rust nightlies and beta (at stable version 1.55) include a change from #![cfg_attr(feature = "nightly", feature(external_doc))] #![cfg_attr(feature = "nightly", doc(include = "../README.md"))] to removing `feature(external_doc)` and also changing the syntax of the second line to #![cfg_attr(feature = "nightly", doc = include_str!("../README.md"))] However. `include_str!` is stable currently, but the syntax of `doc = ` is expressly disallowed. This gives me four options: 1. Don't build documentation (bad) 2. Copy-pasta README.md into src/lib.rs (also bad) 3. Support only beta/nightly but not stable (completely untennable for a crate with ~14 million downloads) 4. Support only stable but not beta/nightly (also untennable) Further, waiting for this to be "fixed" by its inclusion in stable Rust in about a week means that our MSRV increases from 1.41 to 1.56, with no changes to actual code (other than how to build documentation) at all, which seems quite unfriendly to downstream dependents who are pinning their rust versions for whatever reason. So, sadly, it seems the most friendly fix is to copy-pasta our README.md into the codebase. (cf. rust-lang/rust#44732, rust-lang/rust#82539)
That relative paths niggle: Has anyone written a macro that fixes the relative links? |
RFC PR: rust-lang/rfcs#1990
RFC text: https://github.com/rust-lang/rfcs/blob/master/text/1990-external-doc-attribute.md
Current documentation
Summary of how to use this:
#![feature(external_doc)]
to your crate."src/some-docs.md"
with some docs to your crate.#[doc(include = "some-docs.md")]
to something that needs some docs. The file path is relative tolib.rs
, so if you want adoc
folder to live alongsidesrc
, then all your paths inside thedoc(include)
attributes need to begin with../doc
.Summary of current status:
Current tasks:
(promote the "failed to load file" warnings to proper lints?)(Make them hard errors instead, per the RFC tweaks and fixes for doc(include) #46858)The text was updated successfully, but these errors were encountered: