不稳定特性

Rustdoc 正在积极开发中,与 Rust 编译器类似,某些特性仅在 nightly 版本中可用。 其中一些特性是新的,在向全世界发布之前需要进行更多测试,而另一些特性则与 Rust 编译器中不稳定的特性相关联。 此处的一些特性需要匹配的 #![feature(...)] 属性才能启用,因此在 Unstable Book 中有更完整的文档记录。 这些部分将在必要时链接到那里。

Nightly 版本限定的功能

这些特性只需要 nightly 构建版本即可运行。 与此页面上的其他特性不同,这些特性不需要使用命令行标志或 crate 中的 #![feature(...)] 属性来“启用”。 这可能会在 stable 版本上使用时为它们提供一些微妙的后备模式,因此请务必小心!

compile-fail 文档测试的错误编号

关于文档测试的章节中所详述,您可以向 doctest 添加 compile_fail 属性,以声明该测试应编译失败。 但是,在 nightly 版本上,您可以选择添加错误编号,以声明 doctest 应发出特定的错误编号

```compile_fail,E0044
extern { fn some_func<T>(x: T); }
```

错误索引使用此功能来确保与给定错误编号相对应的示例正确发出该错误代码。 但是,不能保证这些错误代码是代码片段从版本到版本发出的唯一内容,因此将来不太可能稳定此功能。

尝试在 stable 版本上使用这些错误编号将导致代码示例被解释为纯文本。

missing_doc_code_examples lint

如果某个条目在其文档中没有代码示例,则此 lint 将发出警告。 可以使用以下方法启用它

#![deny(rustdoc::missing_doc_code_examples)]

对于无法实例化/调用的条目(例如字段、变体、模块、关联的 trait/impl 条目、impl 块、静态变量和常量),不会发出此警告。 对于外部条目、别名、extern crate 和导入,也不会发出此警告。

#[doc] 属性的扩展

这些特性的运行方式是扩展 #[doc] 属性,因此可以被编译器捕获,并使用 crate 中的 #![feature(...)] 属性启用。

#[doc(cfg)]:记录代码存在的平台或特性要求

您可以使用 #[doc(cfg(...))] 来告诉 Rustdoc 哪些平台会显示哪些条目。 这有两个效果

  1. doctest 将仅在适当的平台上运行,并且
  2. 当 Rustdoc 呈现该条目的文档时,它将附带一个横幅,解释该条目仅在某些平台上可用。

#[doc(cfg)] 旨在与 #[cfg(doc)] 一起使用。 例如,#[cfg(any(windows, doc))] 将在 Windows 上或在文档处理期间保留该条目。 然后,添加一个新属性 #[doc(cfg(windows))] 将告诉 Rustdoc 该条目应该在 Windows 上使用。 例如

#![allow(unused)]
#![feature(doc_cfg)]

fn main() {
/// Token struct that can only be used on Windows.
#[cfg(any(windows, doc))]
#[doc(cfg(windows))]
pub struct WindowsToken;

/// Token struct that can only be used on Unix.
#[cfg(any(unix, doc))]
#[doc(cfg(unix))]
pub struct UnixToken;

/// Token struct that is only available with the `serde` feature
#[cfg(feature = "serde")]
#[doc(cfg(feature = "serde"))]
#[derive(serde::Deserialize)]
pub struct SerdeToken;
}

在此示例中,令牌将仅在其各自的平台上显示,但它们都将显示在文档中。

引入 #[doc(cfg(...))] 是为了供标准库使用,目前需要 #![feature(doc_cfg)] feature gate。 有关更多信息,请参阅 Unstable Book 中的章节其追踪 issue

doc_auto_cfg:自动生成 #[doc(cfg)]

doc_auto_cfg#[doc(cfg)] 特性的扩展。 有了它,您不再需要添加 #[doc(cfg(...)],除非您想覆盖默认行为。 因此,如果我们采用之前的源代码

#![allow(unused)]
#![feature(doc_auto_cfg)]

fn main() {
/// Token struct that can only be used on Windows.
#[cfg(any(windows, doc))]
pub struct WindowsToken;

/// Token struct that can only be used on Unix.
#[cfg(any(unix, doc))]
pub struct UnixToken;

/// Token struct that is only available with the `serde` feature
#[cfg(feature = "serde")]
#[derive(serde::Deserialize)]
pub struct SerdeToken;
}

它将呈现几乎相同的结果,区别在于 doc 也将显示。 要修复此问题,您可以使用 doc_cfg_hide

#![allow(unused)]
#![feature(doc_cfg_hide)]
#![doc(cfg_hide(doc))]
fn main() {
}

并且 doc 将不再显示!

将您的 trait 添加到“Notable traits”对话框

Rustdoc 保留了一个 trait 列表,这些 trait 被认为是实现它们的类型的“基本” trait。 这些 trait 旨在成为其实现者的主要接口,并且通常是其类型上可记录的 API 的大部分。 因此,当给定类型实现这些 trait 之一时,Rustdoc 将会跟踪,并在函数返回这些类型之一时特别注意它。 这就是“Notable traits”对话框,可通过函数旁边的带圆圈的 i 按钮访问,单击该按钮时会显示该对话框。

在标准库中,此列表中的某些 trait 是 IteratorFutureio::Readio::Write。 但是,这些 trait 不是作为硬编码列表实现的,而是在它们上面有一个特殊的标记属性:#[doc(notable_trait)]。 这意味着您可以将此属性应用于您自己的 trait,以将其包含在文档中的“Notable traits”对话框中。

#[doc(notable_trait)] 属性目前需要 #![feature(doc_notable_trait)] feature gate。 有关更多信息,请参阅 Unstable Book 中的章节其追踪 issue

从文档中排除某些依赖项

标准库使用了多个依赖项,而这些依赖项又使用了标准库中的多种类型和 trait。 此外,还有几个编译器内部 crate 不被认为是官方标准库的一部分,因此将其包含在文档中会分散注意力。 仅排除它们的 crate 文档是不够的,因为 trait 实现的信息会同时出现在类型和 trait 的页面上,而它们可能位于不同的 crate 中!

为了防止内部类型包含在文档中,标准库在其 extern crate 声明中添加了一个属性:#[doc(masked)]。 这会导致 Rustdoc 在构建 trait 实现列表时“屏蔽”来自这些 crate 的类型。

#[doc(masked)] 属性旨在在内部使用,并且需要 #![feature(doc_masked)] feature gate。 有关更多信息,请参阅 Unstable Book 中的章节其追踪 issue

文档化原始类型

这仅供 Rust 编译器内部使用。

由于原始类型在编译器中定义,因此没有地方附加文档属性。 #[rustc_doc_primitive = "..."] 属性由标准库使用,以提供一种为原始类型生成文档的方法,并且需要 #![feature(rustc_attrs)] 才能启用。

文档化关键字

这仅供 Rust 编译器内部使用。

Rust 关键字在标准库中进行了文档化(例如查找 match)。

为此,使用了 #[doc(keyword = "...")] 属性。 例子

#![allow(unused)]
#![feature(rustdoc_internals)]
#![allow(internal_features)]

fn main() {
/// Some documentation about the keyword.
#[doc(keyword = "break")]
mod empty_mod {}
}

这仅供官方 Rust 项目使用。

内部 Rustdoc 页面(如 settings.html 和 scrape-examples-help.html)显示 Rust 标志。 此标志被跟踪为静态资源。 属性 #![doc(rust_logo)] 使此相同的内置资源充当主标志。

#![allow(unused)]
#![feature(rustdoc_internals)]
#![allow(internal_features)]
#![doc(rust_logo)]
fn main() {
//! This crate has the Rust(tm) branding on it.
}

其他 nightly 特性的影响

这些仅限 nightly 的特性主要与 Rustdoc 无关,但对生成的文档具有方便的影响。

fundamental 类型

使用 #[fundamental] 注释类型主要影响关于泛型类型的 coherence 规则,即它们会改变其他 crate 是否可以为该类型提供实现。 Unstable Book 链接到更多信息

对于文档,这还有一个额外的副作用:如果在一个方法在 F<T> (或 F<&T>) 上实现,其中 F 是一个 fundamental 类型,那么该方法不仅在关于 F 的页面上记录,而且还在关于 T 的页面上记录。 从某种意义上说,它使类型对 Rustdoc 透明。 这对于充当带注释的指针的类型(例如 Pin<&mut T>)尤其方便,因为它确保了仅通过这些带注释的指针实现的方法仍然可以在它们作用的类型中找到。

如果 fundamental 特性对 coherence 的影响不是预期的,则可以将此类类型标记为仅用于文档目的的 fundamental 类型,方法是引入自定义特性并将 fundamental 的使用限制为构建文档时。

不稳定的命令行参数

这些特性通过将命令行标志传递给 Rustdoc 来启用,但所讨论的标志本身被标记为不稳定。 要使用这些选项中的任何一个,请将 -Z unstable-options 以及有问题的标志传递给命令行上的 Rustdoc。 要从 Cargo 执行此操作,您可以使用 RUSTDOCFLAGS 环境变量或 cargo rustdoc 命令。

--markdown-before-content:在内容之前包含渲染的 Markdown

使用此标志看起来像这样

$ rustdoc src/lib.rs -Z unstable-options --markdown-before-content extra.md
$ rustdoc README.md -Z unstable-options --markdown-before-content extra.md

就像 --html-before-content 一样,这允许您在 <body> 标记内但在 rustdoc 通常会在渲染文档中生成的其他内容之前插入额外内容。 但是,rustdoc 不是直接逐字插入文件,而是将文件通过 Markdown 渲染器传递,然后再将结果插入到文件中。

--markdown-after-content:在内容之后包含渲染的 Markdown

使用此标志看起来像这样

$ rustdoc src/lib.rs -Z unstable-options --markdown-after-content extra.md
$ rustdoc README.md -Z unstable-options --markdown-after-content extra.md

就像 --html-after-content 一样,这允许您在 </body> 标记之前但在 rustdoc 通常会在渲染文档中生成的其他内容之后插入额外内容。 但是,rustdoc 不是直接逐字插入文件,而是将文件通过 Markdown 渲染器传递,然后再将结果插入到文件中。

--playground-url:控制 playground 的位置

使用此标志看起来像这样

$ rustdoc src/lib.rs -Z unstable-options --playground-url https://play.rust-lang.org/

渲染 crate 的文档时,此标志给出 Rust Playground 的基本 URL,用于生成 Run 按钮。 与 --markdown-playground-url 不同,此参数适用于独立的 Markdown 文件 Rust crate。 这与向您的 crate 根目录添加 #![doc(html_playground_url = "url")] 的方式相同,如 关于 #[doc] 属性的章节中所述。 请注意,官方 Rust Playground (https://play.rust-lang.org) 并非提供所有 crate,因此如果您的示例需要您的 crate,请确保您提供的 playground 提供了您的 crate。

如果在渲染独立的 Markdown 文件时同时存在 --playground-url--markdown-playground-url,则 --markdown-playground-url 给出的 URL 将优先。 如果在渲染 crate 文档时同时存在 --playground-url#![doc(html_playground_url = "url")],则属性将优先。

--sort-modules-by-appearance:控制模块页面上的条目排序方式

使用此标志看起来像这样

$ rustdoc src/lib.rs -Z unstable-options --sort-modules-by-appearance

通常,当 rustdoc 在模块页面中打印条目时,它会按字母顺序对其进行排序(考虑到它们的稳定性以及以数字结尾的名称)。 将此标志传递给 rustdoc 将禁用此排序,而是使其按照条目在源代码中出现的顺序打印条目。

--show-type-layout:向每个类型的文档添加一个描述其内存布局的部分

使用此标志看起来像这样

$ rustdoc src/lib.rs -Z unstable-options --show-type-layout

传递此标志后,rustdoc 将在每个类型文档页面的底部添加一个“布局”部分,其中包含 rustc 计算的类型内存布局摘要。 例如,rustdoc 将显示该类型的值在内存中占用的字节大小。

请注意,大多数布局信息完全不稳定,甚至可能在编译之间有所不同。

--resource-suffix:修改 crate 文档中 CSS/JavaScript 的名称

使用此标志看起来像这样

$ rustdoc src/lib.rs -Z unstable-options --resource-suffix suf

渲染文档时,rustdoc 会创建多个 CSS 和 JavaScript 文件作为输出的一部分。 由于所有这些文件都从每个页面链接,如果您需要专门缓存它们,更改它们的位置可能会很麻烦。 此标志将重命名输出中的所有这些文件,以在文件名中包含后缀。 例如,使用上述命令,light.css 将变为 light-suf.css

使用此标志看起来像这样

$ rustdoc src/lib.rs -Z unstable-options --extern-html-root-url some-crate=https://example.com/some-crate/1.0.1

通常,当 rustdoc 想要链接到来自不同 crate 的类型时,它会在两个位置查找:输出目录中已存在的文档,或在另一个 crate 中设置的 #![doc(doc_html_root)]。 但是,如果您想链接到在这些位置都不存在的文档,则可以使用这些标志来控制该行为。 当给定 --extern-html-root-url 标志并且名称与您的依赖项之一匹配时,rustdoc 将对这些文档使用该 URL。 请记住,如果这些文档存在于输出目录中,则这些本地文档仍将覆盖此标志。

-Z force-unstable-if-unmarked

使用此标志看起来像这样

$ rustdoc src/lib.rs -Z force-unstable-if-unmarked

这是一个内部标志,旨在用于标准库和编译器,它将 #[unstable] 属性应用于任何没有其他稳定性属性的依赖 crate。 这允许 rustdoc 为编译器 crate 和标准库生成文档,因为在构建这些 crate 时,为 rustc 提供了等效的命令行参数。

--index-page:为文档提供顶级着陆页

此功能允许您使用给定的 markdown 文件生成索引页。 rust 文档索引就是一个很好的例子。

有了这个,您将拥有一个页面,您可以在 crate 的顶部根据需要自定义该页面。

使用 index-page 选项也会启用 enable-index-page 选项。

--enable-index-page:为文档生成默认索引页

此功能允许生成默认索引页,其中列出了生成的 crate。

--nocapture:禁用测试的输出捕获

当将此标志与 --test 一起使用时,rustdoc 不会捕获测试的输出(stdout 和 stderr)。 相反,输出将定向到您的终端,就像您手动运行测试可执行文件一样。 这对于调试测试特别有用!

--check:仅检查文档

当提供此标志时,rustdoc 将类型检查和 lint 您的代码,但不会生成任何文档或运行您的 doctest。

使用此标志看起来像

rustdoc -Z unstable-options --check src/lib.rs

--static-root-path:控制 HTML 输出中静态文件的加载方式

使用此标志看起来像这样

$ rustdoc src/lib.rs -Z unstable-options --static-root-path '/cache/'

此标志控制 rustdoc 如何链接到 HTML 页面上的静态文件。 如果您托管了许多由相同版本的 rustdoc 生成的 crate 文档,则可以使用此标志将 rustdoc 的 CSS、JavaScript 和字体文件缓存在单个位置,而不是每个“文档根目录”(分组到同一输出目录中的 crate 文档,例如使用 cargo doc)复制一次。 每个 crate 的文件(如搜索索引)仍将从文档根目录加载,但使用 --resource-suffix 重命名的任何内容都将从给定路径加载。

--persist-doctests:在运行后保留 doctest 可执行文件

使用此标志看起来像这样

$ rustdoc src/lib.rs --test -Z unstable-options --persist-doctests target/rustdoctest

此标志允许您在 doctest 编译或运行后保留 doctest 可执行文件。 通常,rustdoc 会在测试后立即丢弃编译后的 doctest,但使用此选项,您可以保留这些二进制文件以进行更深入的测试。

--show-coverage:计算具有文档的条目的百分比

使用此标志看起来像这样

$ rustdoc src/lib.rs -Z unstable-options --show-coverage

它会生成类似这样的内容

+-------------------------------------+------------+------------+------------+------------+
| File                                | Documented | Percentage |   Examples | Percentage |
+-------------------------------------+------------+------------+------------+------------+
| lib.rs                              |          4 |     100.0% |          1 |      25.0% |
+-------------------------------------+------------+------------+------------+------------+
| Total                               |          4 |     100.0% |          1 |      25.0% |
+-------------------------------------+------------+------------+------------+------------+

如果您想确定您的 crate 中有多少个条目有文档,请将此标志传递给 rustdoc。 当它收到此标志时,它将计算您的 crate 中具有文档的公共条目的数量,并打印出计数和百分比,而不是生成文档。

关于 rustdoc 在此指标中计数的某些方法论说明

  • Rustdoc 将仅计算来自您的 crate 的条目(即,从其他 crate 重新导出的条目不计数)。
  • 直接写入固有 impl 块的文档不计入,即使它们的文档注释已显示,因为 Rust 代码中的常见模式是将所有固有方法写入相同的 impl 块。
  • trait 实现中的条目不计入,因为这些 impl 将继承来自 trait 本身的任何文档。
  • 默认情况下,仅计算公共条目。 要同时计算私有条目,请同时传递 --document-private-items

可以使用内置的 missing_docs lint 查看未记录的公共条目。 可以使用 Clippy 的 missing_docs_in_private_items lint 查看未记录的私有条目。

计算代码示例遵循以下规则

  1. 默认情况下,这些条目不计算在内
  • struct/union 字段
  • enum 变体
  • 常量
  • 静态变量
  • typedef
  1. 如果先前列出的条目之一具有代码示例,则将对其进行计数。

JSON 输出

--output-format json 与此选项一起使用时,它将以 JSON 格式显示 coverage 信息。 例如,这是包含一个已记录条目和一个未记录条目的文件的 JSON

#![allow(unused)]
fn main() {
/// This item has documentation
pub fn foo() {}

pub fn no_documentation() {}
}
{"no_std.rs":{"total":3,"with_docs":1,"total_examples":3,"with_examples":0}}

请注意,第三个条目是 crate 根,在这种情况下,它没有文档。

如果您希望 JSON 输出显示在 stdout 上而不是生成文件,则可以使用 -o -

-w/--output-format:输出格式

--output-format json 以实验性的 JSON 格式发出文档。 --output-format html 无效,并且在 stable 工具链上也被接受。

工具链 crate(stdalloccoretestproc_macro)的 JSON 输出可通过 rust-docs-json rustup 组件获得。

rustup component add --toolchain nightly rust-docs-json

然后,json 文件将存在于 rustup 工具链目录的 share/doc/rust/json/ 目录中。

它也可以与 --show-coverage 一起使用。 请查看其 documentation 以获取更多信息。

--enable-per-target-ignores:允许 doctest 使用 ignore-foo 样式过滤器

使用此标志看起来像这样

$ rustdoc src/lib.rs -Z unstable-options --enable-per-target-ignores

此标志允许您使用 compiletest 样式的 ignore-foo 过滤器标记 doctest,如果目标三元组字符串包含 foo,则阻止 rustdoc 运行该测试。 例如

#![allow(unused)]
fn main() {
///```ignore-foo,ignore-bar
///assert!(2 == 2);
///```
struct Foo;
}

当构建目标是 super-awesome-fooless-bar-awesome 时,这将不会运行。 如果未启用该标志,则 rustdoc 将消耗过滤器,但不会对其执行任何操作,并且以上示例将针对所有目标运行。 如果您想为旧版本的 rustdoc 保留向后兼容性,可以使用

#![allow(unused)]
fn main() {
///```ignore,ignore-foo
///assert!(2 == 2);
///```
struct Foo;
}

在旧版本中,这将在所有目标上被忽略,但在较新版本中,ignore-gnu 将覆盖 ignore

--runtool--runtool-arg:用于运行测试的程序;传递给它的参数

使用这些选项看起来像这样

$ rustdoc src/lib.rs -Z unstable-options --runtool runner --runtool-arg --do-thing --runtool-arg --do-other-thing

这些选项可用于在程序下运行 doctest,并向该程序传递参数。 例如,如果您想在 valgrind 下运行 doctest,您可以运行

$ rustdoc src/lib.rs -Z unstable-options --runtool valgrind

另一个用例是在模拟器或虚拟机中运行测试。

--with-examples:将条目用法示例作为文档包含在内

此选项与 --scrape-examples-target-crate--scrape-examples-output-path 结合使用,用于实现 RFC #3123 中的功能。 在 crate 及其反向依赖项中查找条目(当前为函数/调用站点)的用法,然后将这些用法作为该条目的文档包含在内。 此功能旨在通过 cargo doc --scrape-examples 使用,但仅限 rustdoc 的工作流程如下所示

$ rustdoc examples/ex.rs -Z unstable-options \
    --extern foobar=target/deps/libfoobar.rmeta \
    --scrape-examples-target-crate foobar \
    --scrape-examples-output-path output.calls
$ rustdoc src/lib.rs -Z unstable-options --with-examples output.calls

首先,必须检查库以生成 rmeta。 然后,将反向依赖项(如 examples/ex.rs)提供给 rustdoc,其中目标 crate 是要记录的 (foobar),输出调用的路径是 (output.calls)。 然后,可以通过 --with-examples 将生成的调用文件传递给后续的 foobar 文档。

要从测试代码(例如,标记为 #[test] 的函数)中抓取示例,请添加 --scrape-tests 标志。

此标志启用在源代码页面中生成链接,使读者可以跳转到类型定义。

--test-builder:类似 rustc 的程序来构建测试

使用此标志看起来像这样

$ rustdoc --test-builder /path/to/rustc src/lib.rs

Rustdoc 将使用提供的程序来编译测试,而不是来自 sysroot 的默认 rustc 程序。

--test-builder-wrapper:包装对测试构建器的调用

使用此标志看起来像这样

$ rustdoc -Zunstable-options --test-builder-wrapper /path/to/rustc-wrapper src/lib.rs
$ rustdoc -Zunstable-options \
    --test-builder-wrapper rustc-wrapper1 \
    --test-builder-wrapper rustc-wrapper2 \
    --test-builder rustc \
    src/lib.rs

与 cargo build.rustc-wrapper 选项类似,此标志接受 rustc 包装器程序。 程序的第一个参数将是测试构建器程序。

可以多次传递此标志以嵌套包装器。

在编译 doctest 时将参数传递给 rustc

如果您想在编译 doctest 时添加选项,可以使用 --doctest-compilation-args 标志。 例如,如果您有

#![allow(unused)]
fn main() {
/// ```
/// #![deny(warnings)]
/// #![feature(async_await)]
///
/// let x = 12;
/// ```
pub struct Bar;
}

并且您在其上运行 rustdoc --test,您将得到

running 1 test
test foo.rs - Bar (line 1) ... FAILED

failures:

---- foo.rs - Bar (line 1) stdout ----
error: the feature `async_await` has been stable since 1.39.0 and no longer requires an attribute to enable
 --> foo.rs:2:12
  |
3 | #![feature(async_await)]
  |            ^^^^^^^^^^^
  |
note: the lint level is defined here
 --> foo.rs:1:9
  |
2 | #![deny(warnings)]
  |         ^^^^^^^^
  = note: `#[deny(stable_features)]` implied by `#[deny(warnings)]`

error: aborting due to 1 previous error

Couldn't compile the test.

failures:
    foo.rs - Bar (line 1)

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.03s

但是,如果您可以使用 --doctest_compilation_args=--cap-lints=warn 将 lint 级别限制为 warning

$ rustdoc --test --doctest_compilation_args=--cap-lints=warn file.rs

running 1 test
test tests/rustdoc-ui/doctest/rustflags.rs - Bar (line 5) ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.06s

参数的解析方式如下:如果遇到 "',它将继续直到找到未转义的字符(没有前置 \)。 如果不在字符串内,则空格字符也会拆分参数。 例子

"hello 'a'\" ok" how are   'you today?'

将拆分为如下内容

[
    "hello 'a'\" ok",
    "how",
    "are",
    "you today?",
]