Skip to content

rustdoc: detect docs that use re-export concat - #162169

Closed
notriddle wants to merge 4 commits into
rust-lang:mainfrom
notriddle:rustdoc/unportable-markdown-re-export-concat
Closed

notriddle wants to merge 4 commits into
rust-lang:mainfrom
notriddle:rustdoc/unportable-markdown-re-export-concat

Conversation

@notriddle

@notriddle notriddle commented Sep 2, 2026 •

Copy link
Copy Markdown
Contributor

DO NOT MERGE WITHOUT SETTING THE DEFAULT BACK TO WARN

This is a prereq for implementing LaTeX math (tracking issue: #162365). Because I want to be able to enable it on a per-docblock basis, re-exports need to be parsed with a different set of markdown parsing extensions than the items they link to, which means we can't just concatenate the strings and parse like we do now.

This was pointed out, in a similar case, by rust-lang/rfcs#3958 (comment)

IMO, markdown that relies on rustdoc’s current behavior is hard to understand, because string concatenation on separate doc comments is stupid.

This lint is mostly added here to run a Crater, so that we can figure out if there are significant numbers of crates are relying on the current behavior.

  • If I find that the number of docs fixed by parsing re-exports separately outnumbers docs that are broken, I think we should just make the change and open PRs against the few crates that were broken.
  • If it turns out that docs are purposefully using this, then I want to ship this compatibility lint for about a year after making the change, just like when people’s docs were being rendered differently because of the pulldown-cmark upgrade.

This is a prereq for implementing LaTeX math. Because I want to be able
to enable it on a per-docblock basis, re-exports need to be parsed with
a different set of markdown parsing extensions than the items they link
to, which means we can't just concatenate the strings and parse.

In any case, markdown that does this would be hard to understand.
We should probably lint on it anyway.
@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue. labels Sep 2, 2026
@rust-log-analyzer

This comment has been minimized.

@rustbot rustbot added the T-rustdoc-frontend Relevant to the rustdoc-frontend team, which will review and decide on the web UI/UX output. label Sep 2, 2026
@rust-log-analyzer

This comment has been minimized.

I want to catch false positives before running crater, but it seems
like all of these really are re-exports.
@notriddle
notriddle force-pushed the rustdoc/unportable-markdown-re-export-concat branch from d0bf5b3 to c9f28f6 Compare September 2, 2026 13:32
@rust-log-analyzer

This comment has been minimized.

@notriddle

Copy link
Copy Markdown
Contributor Author

@bors try

@craterbot run mode=rustdoc

@craterbot

Copy link
Copy Markdown
Collaborator

🚨 Error: missing start toolchain

🆘 If you have any trouble with Crater please ask in t-infra on Zulip
ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Sep 2, 2026
…rt-concat, r=<try>

rustdoc: detect docs that use re-export concat
@rust-bors

rust-bors Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

☀️ Try build successful (CI)
Build commit: da3f5c3 (da3f5c31e5535b3dc210067de660a45784ae1e9c)
Base parent: 824336a (824336ad4127ce295849937a24c08a4aeff6ada7)

@notriddle

Copy link
Copy Markdown
Contributor Author

@craterbot run mode=rustdoc

@craterbot

Copy link
Copy Markdown
Collaborator

👌 Experiment pr-162169 created and queued.
🤖 Automatically detected try build da3f5c3
🔍 You can check out the queue and this experiment's details.

ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

@craterbot craterbot added S-waiting-on-crater Status: Waiting on a crater run to be completed. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Sep 2, 2026
@craterbot

Copy link
Copy Markdown
Collaborator

🚧 Experiment pr-162169 is now running

ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

@notriddle notriddle mentioned this pull request Sep 6, 2026
1 of 6 tasks
@craterbot

Copy link
Copy Markdown
Collaborator

🎉 Experiment pr-162169 is completed!
📊 1053 regressed and 1 fixed (1103137 total)
📊 5067 spurious results on the retry-regressed-list.txt, consider a retry1 if this is a significant amount.
📰 Open the summary report.

⚠️ If you notice any spurious failure please add them to the denylist!
ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

Footnotes

  1. re-run the experiment with crates=https://crater-reports.s3.amazonaws.com/pr-162169/retry-regressed-list.txt ↩

@craterbot craterbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-crater Status: Waiting on a crater run to be completed. labels Sep 8, 2026
@notriddle

Copy link
Copy Markdown
Contributor Author

Okay, I checked about a dozen random-ish crates, and it seems like switching to separate parsing would be, at worse, neutral.

For example, this line from plotters:

https://github.com/plotters-rs/plotters/blob/c63248e0cf7c611185361ac492003e8a87d52ea8/plotters/src/style/mod.rs#L12

Results in this:

image

@notriddle notriddle closed this Sep 10, 2026
@rustbot rustbot removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Sep 10, 2026
notriddle added a commit to notriddle/rust that referenced this pull request Oct 3, 2026
Change the way Rustdoc behaves when a re-export and its original item both have doc comments.

In other words, code like this:

```rust
/// original
struct Foo;

/// re-export
pub use Foo as Bar;
```

In the current version of Rustdoc, the rendering is equivalent to:

```rust
/// re-export
/// original
pub use Bar;
```

Because there's no blank line between the comments, you get "re-export original" as a single paragraph.

The new version, introduced by this pull request, renders two paragraphs. It actually runs the Markdown parser separately for both items, so link refdefs, footnotes, and, in the future, syntax features are scoped separately.

This change is a pre-requisite for [LaTeX support](rust-lang#162365), because it introduces the notion of syntax features into Rustdoc's Markdown. It lets you turn tex_math_dollars support on and off.

As part of this change, a bug related to intra-doc links is also fixed. This shows up when the reexport and the item both have intra-doc links with the same visible path, but where they resolve to different items. The bug is demonstrated in
`tests/rustdoc-html/reexport/link-with-same-name-but-different-destination.rs`.

The other test case changes demonstrate that this is, technically, a breaking change. When I ran [a Crater test](rust-lang#162169) for docs that rely on this behavior, though, it seemed most authors weren't relying on it.
@notriddle

notriddle commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor Author

While considering the policy that should be considered for the rustdoc stability policy, a dozen seemed too low. Yes, I'm pretty sure this particular change was fine, but I really don't feel comfortable giving that much leeway to anyone, even my future self.

So, here's fifty crates, chosen from the crater run. I manually inspected the re-export and the original item's doc comments, verifying that both could be rendered as separate markdown documents without obviously diverging from what the doc author intended.

crate name re-export original is it broken?
armdb 0.12.0 Deprecated alias... "Renamed from Indexed..." No
arenabuddy_core 0.5.12 Re-export the card... Card represents a Magic... No
radiochron Current wire/storage schema... Current fleet-safe...
async-hybrid-sleep 0.1.1 Re-export of... The default ... No
codexia Default upstream... Default codex... No
biga-spm-rs Re-export calendar trait Trait for types that... No
bracket-algorithm-traits-0.8.7 Algorithm2D support Implement these... No
dial9-core 0.5.0 References to the sealed segment... A sealed trace... No
infotheory 1.1.1 SIMD lane-parallel... 8-way interleaved... No
into-parts 1.0.0 Re-export of the IntoParts trait... A trait for... NO
ion-fmt 0.15.0 Display wrapper and helpers... Spacing behavior... No
lirays 0.1.2 Model types used... Configuration used... No
magic_migrate 2.0.0 A generic wrapper... use serde No
loregrep 0.6.0 Main LoreGrep API... The main struct... No
netsock 0.8.0 Returns sockets using... Returns sockets with...
nflz 1.0.2 See crate::error::NFLZError Main error of the library No
pauling 0.1.0 The core traits... Traits that describe... No
pdfium 0.10.4 Duplex types... Duplex types... No
pth 0.44.1 Basic functionality A new type representing an absolute path... No
rotary-add 0.2.1 CycleAdd works on ranges... Trait with methods for cyclical arithmetic... No
roaring-bloom-filter 0.2.0 A scalable bloom filter... Scalable bloom filter (SBF) No
rocket_okapi 0.9.0 Expose this to the public... Given an object... No
rsbinder 0.10.0 Register-side public service. RAII handle returned by... No
runtime-context 0.1.1 Re-export the main... Runtime context... No
rustws 1.0.0 The errors that can be thrown during runtime... The kind of exceptions the program can throw... No
rusty_vp9 0.1.1 The ENCODER's stage... Primitive profiler... No
sandbox-run 0.53.0 Whether the running kernel... Whether the running kernel... No
sanitizer 1.0.0 Sanitizer methods for strings The Sanitizer structure... No
scirs2-integrate 0.6.5 Re-exports Solve ODE using the Dormand-Prince method... No
scirs2-autograd 0.6.5 Matrix trig... Compute general matrix... No
schematic 0.20.2 Renders Typescript types. Format of a TypeScript enum. No
scd30-interface 2.0.0 Blocking interface for the SCD30 Implementation of the SCD30’s interface No
scattered-collect 0.22.1 Declarative form... no doc comment False positive (the warned-about item has no doc comment)
satd-events-client 0.5.0 Parse a raw wire txid into... Parse a raw wire txid... No
sashite-feen 0.2.0 Canonical FEEN serialization... Encodes an owned... No
sapper 0.2.0 PathParams is the parameter type referring... Path parameter type No
sanitizer 1.0.0 Sanitizer methods for strings The Sanitizer structure... No
trace_id 0.1.1 Re-export core trace ID struct 追踪ID结构体 No
tino 0.1.24 Parsed tino command-line configuration... Parsed tino command-line configuration... No
timely 0.31.0 A wrapper that indicates a serialization/deserialization strategy. A wrapper that indicates bincode as the serialization/deserialization strategy. No
tikv-client 0.4.0 Protobuf-generated region-level error returned by TiKV... Error wraps all region errors, indicates an error encountered by a request. No
tidecoin_hashes 0.20.0 HASH-160: Alias for the [hash160::Hash] hash type. Output of the HASH160 hash function. (RIPEMD160(SHA256)) No
thryd 0.7.3 Model-related re-exports... equest payload for generating text completions... No
tftp_client 0.3.0 The blocking functions are the default Upload a file via tftp No
tfhe-hpu-backend 0.6.0 Module containing the definition of the HpuGlweCiphertext... Load entities and type related stuff No
textual 1.1.0 Resolve a custom widget's component-class CSS... Resolve the component-class CSS... No
tetherscript 0.1.0-alpha.31 Revoke every socket grant on this thread... Revoke every socket grant on this thread... No
test-foo-bar-sha2 0.0.8 use it if we want to use hacl SHA2 512... No
terrors 0.3.3 Similar to anonymous unions... OneOf is an open sum type... No
termint 0.9.0 A trait implemented by all the widgets... Generic text render function... No

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. 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.

4 participants