-
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
[rustdoc-json] JSON no longer inlines #99287
[rustdoc-json] JSON no longer inlines #99287
Conversation
rustdoc-json-types is a public (although nightly-only) API. If possible, consider changing |
This looks great to me, thank you for picking it up! |
This comment has been minimized.
This comment has been minimized.
35769c1
to
451e2f1
Compare
Fixed the tidy issue. |
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.
Thanks a lot for working on this! ❤️
When I ran cargo public-api
regression tests with this change, I caught a seemingly big semantic change, because some tests started failing.
Consider this code in src/lib.rs
(I am using a type
but e.g. fn
has the same problem, and I imagine any other item type.):
#![feature(no_core)]
#![no_core]
#![no_std]
mod stripped {
pub type T = usize;
}
pub use stripped::T;
before this PR, the pub use
did not emit any JSON item by itself. Instead, there were only two items in rustdoc JSON:
- The crate module (
"kind": "module"
) - The typedef (
"kind": "typedef"
)
After this change, the pub use
itself is also emitted. This runs contrary to rustdoc HTML output, where the pub use
will not be present by default. There are now four items:
- The crate module (
"kind": "module"
,"is_crate": true
) - The typedef (
"kind": "typedef"
) - The stripped module (
"kind": "module"
,"is_stripped": true
) - The
pub use
("kind": "import"
)
I don't think we want the pub use
JSON item in the output by default? Because that is not what cargo doc
HTML shows by default.
...on the other hand, what should we do instead? We do not inline any longer.
Silly idea maybe, but can't we inline JSON as a very last step? So that the output becomes the same as before, but internally we do not do any inlining, so that all ICEs are fixed.
In short, this PR breaks my tool, so if we could go a bit gently forward, I would appreciate it :)
src/librustdoc/json/conversions.rs
Outdated
clean::KeywordItem(_) => return None, | ||
clean::StrippedItem(ref inner) => { | ||
match &**inner { | ||
// We document non-empty stripped modules as a special StrippedModule type, to |
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.
StrippedModule
is mentioned, but does not exist any longer, needs to be updated for Module::is_stripped
.
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.
Oh indeed, good catch!
The original PR did it the same way, so I'm surprised it's become an issue in-between. Inlining after will very likely be quite tricky and bring back most of the previous issues (conflicting IDs). Also, the JSON output cannot be the same as the HTML one. Let me take an example: mod private_mod {
pub struct Foo;
}
pub fn foo() -> Foo {} With this code, the HTML will not create a link for Does it make sense? 😅 EDIT: I just thought about something: the JSON output was already showing |
I've further looked into this change from my side this morning and have no blocking concerns any longer. Feel free to go ahead with merging this (as if I have any authority over that 😅). (After this has landed I will experiment with letting my tool inline the JSON itself to get back the old behaviour. Seems like that could work. If it doesn't, it is not the end of the world.) Looking forward to seeing those ICEs going away! 💪
This is probably not a new issue, it's simply that I never ran my test suite on the old PR, because
|
Not an "authority" but you're a user providing feedback, which is very important for us. If there is no more issue for you, then I think we can indeed go forward. Thanks a lot for your help!
I guess you already thought about it but if the type is a reexport, why not linking all its items directly into the top level on your side? That shouldn't require too much code hopefully. Since @notriddle approved it too, let's go. :) @bors r+ |
📌 Commit 451e2f1bbfce876113cf7565015b219eb7e3e8d4 has been approved by It is now in the queue for this repository. |
@bors r=notriddle |
💡 This pull request was already approved, no need to approve it again.
|
📌 Commit 451e2f1bbfce876113cf7565015b219eb7e3e8d4 has been approved by It is now in the queue for this repository. |
Just realized that I forgot to apply the comments... @bors r- |
451e2f1
to
b95b138
Compare
Let's go again! @bors r=notriddle |
…askrgr Rollup of 10 pull requests Successful merges: - rust-lang#98582 (Allow destructuring opaque types in their defining scopes) - rust-lang#99213 (migrate some of `rustc_passes::check_attr`'s diagnostics and derive improvements) - rust-lang#99258 (Provide structured suggestion for dropped temp value) - rust-lang#99259 (interpret/visitor: support visiting with a PlaceTy) - rust-lang#99287 ([rustdoc-json] JSON no longer inlines) - rust-lang#99290 (Revert "Highlight conflicting param-env candidates") - rust-lang#99316 (docs: add missing word) - rust-lang#99317 (Borrow Vec<T, A> as [T]) - rust-lang#99323 (Fix flakyness of GUI tests) - rust-lang#99342 (Avoid some `Symbol` to `String` conversions) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
As I was working on doing the inlining myself in my tool, I think I bumped into an unintended regression from this change. Step-by-step:Paste the following in either # Create a library with a trait with one associated function
echo '
pub trait A {
fn trait_a_fn();
}
' > a.rs
# Create another library that depends on the first library
echo '
pub use a::A;
' > b.rs
# Check with what toolchains rustdoc JSON is generated for `trait_a_fn`
for toolchain in nightly-2022-07-16 nightly-2022-07-17; do
# Create a directory with output from each toolchain
mkdir -p $toolchain
# Compile the library
rustc +$toolchain --edition=2021 \
--crate-type rlib -o $toolchain/liba.rlib a.rs
# Generate rustdoc JSON for both libraries
rustdoc +$toolchain --edition=2021 \
--extern a=$toolchain/liba.rlib \
-Z unstable-options --output-format json \
-o $toolchain b.rs
# See if rustdoc JSON for `trait_a_fn` was generated
grep --silent trait_a_fn $toolchain/b.json && echo "rustdoc JSON for 'trait_a_fn' was generated by '$toolchain'"
done Expected output:
Actual output:
Would you agree this looks like an unintentional regression? Can you reproduce? Without rustdoc JSON for Let me know if you would like me to file a separate issue for this, and I will happily do it. |
No, it seems to be exactly the point of this PR (but maybe I misunderstood your issue?). |
Sorry for being unclear. My impression was that we always generated one big chunk of rustdoc JSON for an entire set of crates. But given your response, I'm starting to think that rustdoc JSON always was intended to generate rustdoc JSON only for one crate at a time. But then, the boundaries are not clear to me. The rustdoc JSON for the small example above contains literally thousands of items that does not have If rustdoc JSON is only designed and intended to be built for for one crate at a time, that means no tool can inline items of imports across crate boundaries, since the IDs are not stable across different builds of rustdoc JSON. If that is how it is supposed to be, that's fine I guess. At least for now :) |
If a foreign type is present in the public API, it has its "definition" in the JSON as well. |
Only partial definition, it seems? Because even though the trait "20:3:1569": {
"id": "20:3:1569",
"crate_id": 20,
"name": "A",
"span": null,
"visibility": "public",
"docs": null,
"links": {},
"attrs": [],
"deprecation": null,
"kind": "trait",
"inner": {
"is_auto": false,
"is_unsafe": false,
"items": [
"20:4:38964"
],
"generics": {
"params": [],
"where_predicates": []
},
"bounds": [],
"implementations": []
}
}, but there is no rustdoc JSON item for the associated function However, I just noticed that if crate To be crystal clear: This do give me the expected output: # Create a library with a trait with one associated function
echo '
pub trait A {
fn trait_a_fn();
}
' > a.rs
# Create another library that depends on the first library
echo '
pub use a::A;
pub struct S;
impl A for S {
fn trait_a_fn() {}
}
' > b.rs
# Check with what toolchains rustdoc JSON is generated for `trait_a_fn`
for toolchain in nightly-2022-07-16 nightly-2022-07-17; do
# Create a directory with output from each toolchain
mkdir -p $toolchain
# Compile the library
rustc +$toolchain --edition=2021 \
--crate-type rlib -o $toolchain/liba.rlib a.rs
# Generate rustdoc JSON for both libraries
rustdoc +$toolchain --edition=2021 \
--extern a=$toolchain/liba.rlib \
-Z unstable-options --output-format json \
-o $toolchain b.rs
# See if rustdoc JSON for `trait_a_fn` was generated
grep --silent trait_a_fn $toolchain/b.json && echo "rustdoc JSON for 'trait_a_fn' was generated by '$toolchain'"
done It could probably be argued that we should not emit rustdoc JSON only partially even in the initial case, but suddenly the current behaviour seems like much less of a problem. |
So foreign items in "imported" foreign items are not in the JSON. Not sure if a bug or not at this point... Seems logical to have direct foreigns but not foreigns of foreigns I suppose. |
Actually, I draw conclusions too quickly. There is an item generated for |
This change was triggered by rust-lang/rust#99287, but it would have made sense to do even without that upstream change.
This new behavior feels "weird" but isn't really; you don't see the definition of a trait without clicking on it in the HTML and if it's a external crate it jumps in that crate you are not staying in the first crate.
This is currently (was ?) the case but I don't think that something that we want. I think @CraftSpider talked about it sometimes ago, I remember something about pruning unnecessary stuff to reduce the size of the JSON and also to avoid this kind of problem. |
This change was triggered by rust-lang/rust#99287, but it would have made sense to do even without that upstream change.
…uillaumeGomez Rustdoc-Json: Don't remove impls for items imported from private modules After rust-lang#99287, items in private modules may still be in the json output, if a public import accesses them. To reflect this, items that are imported need to be marked as retained in the `Stripper` pass, so their impls arn't removed by `ImplStripper`. [More context on zulip](https://rust-lang.zulipchat.com/#narrow/stream/266220-rustdoc/topic/Populating.20cache.2Eimpls), thanks to @ jyn514 for helping debug this. `@rustbot` modify labels: +A-rustdoc-json +T-rustdoc r? `@GuillaumeGomez` Fixes rust-lang#100252 Fixes rust-lang#100242
…uillaumeGomez Rustdoc-Json: Don't remove impls for items imported from private modules After rust-lang#99287, items in private modules may still be in the json output, if a public import accesses them. To reflect this, items that are imported need to be marked as retained in the `Stripper` pass, so their impls arn't removed by `ImplStripper`. [More context on zulip](https://rust-lang.zulipchat.com/#narrow/stream/266220-rustdoc/topic/Populating.20cache.2Eimpls), thanks to @ jyn514 for helping debug this. ``@rustbot`` modify labels: +A-rustdoc-json +T-rustdoc r? ``@GuillaumeGomez`` Fixes rust-lang#100252 Fixes rust-lang#100242
Fixes #98007.
Fixes #96161.
Fixes #83057.
Fixes #83720.
I took over #93518 and applied the comments and added more tests.
There was one thing missing (which is in the second commit): if a non-exported item was used in a public API but not reexported, it was still missing.
cc @CraftSpider @Urgau @Enselic
r? @notriddle