Skip to content
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

Remove CURRENT_DEPTH thread-local variable #82815

Closed
wants to merge 4 commits into from

Conversation

camelid
Copy link
Member

@camelid camelid commented Mar 5, 2021

Closes #82742. 🎉

This PR has a fairly large diff, but most of the changes are very small - just
threading the new depth parameter through a bunch of functions.

This PR is draft because there are a few things that need to be resolved
before it should be merged. I have marked those spots with review comments.

r? @jyn514

@camelid camelid added C-cleanup Category: PRs that clean code up or issues documenting cleanup. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue. labels Mar 5, 2021
@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Mar 5, 2021
Comment on lines -2295 to +2296
vis.print_with_space(cx.tcx, def_id, &cx.cache),
// FIXME(camelid): this might create broken links!
vis.print_with_space(cx.tcx, def_id, &cx.cache, 0),
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this has the same behavior as before, but we should probably test it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this will break for macros in submodules (e.g. pub mod inner { pub macro foo() {} }).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, so it looks like we don't use links in macro visibilities on nightly anyway:

#![feature(decl_macro)]

pub mod inner1 {
    pub mod inner2 {
        pub mod inner3 {
            pub(in crate::inner1) macro foo() {}
        }
    }
}

image

So I'm not sure how to test the changes :/

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, so it looks like we don't use links in macro visibilities on nightly anyway:

That sounds like a bug, could you open an issue?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue: #83000. Nice issue number :)

Comment on lines -2302 to +2304
vis.print_with_space(cx.tcx, def_id, &cx.cache),
// FIXME(camelid): this might create broken links!
vis.print_with_space(cx.tcx, def_id, &cx.cache, 0),
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above.

Comment on lines -417 to +420
return Generic(Symbol::intern(&format!("{:#}", path.print(&cx.cache))));
// FIXME(camelid): I hope passing 0 as the depth doesn't break anything....
// Then again, I think used to be 0 anyway through CURRENT_DEPTH
// because (I think) rendering hadn't started yet.
return Generic(Symbol::intern(&format!("{:#}", path.print(&cx.cache, 0))));
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think same as above.

Copy link
Member

@jyn514 jyn514 Mar 5, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change makes me nervous, can you say why you think rendering hadn't started?

I don't know exactly when this path is hit, path.segment.len() == 1 seems really strange because it doesn't leave any space for the crate name and I don't see any other reason to special case 1 path segment. Maybe add an unconditional panic!() so we have a test case?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change makes me nervous

I understand, these changes make me a bit nervous too :)

can you say why you think rendering hadn't started?

My understanding is that all cleaning happens before rendering, so CURRENT_DEPTH is always its initial value of 0. Is that not true?

Maybe add an unconditional panic!() so we have a test case?

Hmm, can you explain more what you mean?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My understanding is that all cleaning happens before rendering, so CURRENT_DEPTH is always its initial value of 0. Is that not true?

Ok, this makes sense to me. The depth is only updated in context.rs:


html/render/context.rs
22:    CURRENT_DEPTH, INITIAL_IDS,
107:        CURRENT_DEPTH.with(|slot| {
421:        CURRENT_DEPTH.with(|s| s.set(0));

and cleaning never happens in html/:

$ rg '\.clean' html/ | wc -l
0

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add an unconditional panic!() so we have a test case?

Hmm, can you explain more what you mean?

I don't know when this line of code will be executed. Can you change it to an unconditional panic and document the standard library so I can see a backtrace of how it happens? If it never happens that probably means the whole thing is unreachable and we don't have to worry about it in the first place.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you change it to an unconditional panic and document the standard library so I can see a backtrace of how it happens? If it never happens that probably means the whole thing is unreachable and we don't have to worry about it in the first place.

@jyn514 It turns out it is reachable! It panicked while documenting core, specifically this path:

DEBUG rustdoc::clean::utils resolve_type(Path { global: false, res: Def(TyParam, DefId(0:140 ~ core[8787]::f32::{impl#0}::to_int_unchecked::Int)), segments: [PathSegment { name: "Int", args: AngleBracketed { args: [], bindings: [] } }] },HirId { owner: DefId(0:139 ~ core[8787]::f32::{impl#0}::to_int_unchecked), local_id: 18 })

I think that path is the Int in the return type of f32::to_int_unchecked().

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think passing a depth of 0 should probably be fine since IIUC paths that resolve to type parameters shouldn't be able to have type parameters themselves...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, that makes sense to me. Could you add a comment about a) when this happens and b) why the depth of 0 is ok?

@camelid
Copy link
Member Author

camelid commented Mar 5, 2021

I think this PR will be very conflict-prone FYI.

Copy link
Member

@jyn514 jyn514 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left some comments on the places where you pointed out a depth of 0. Can you point to where the depth is incremented and decremented? It's hard to find the important changes because the diff is big 😅

Comment on lines -2295 to +2296
vis.print_with_space(cx.tcx, def_id, &cx.cache),
// FIXME(camelid): this might create broken links!
vis.print_with_space(cx.tcx, def_id, &cx.cache, 0),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this will break for macros in submodules (e.g. pub mod inner { pub macro foo() {} }).

Comment on lines -417 to +420
return Generic(Symbol::intern(&format!("{:#}", path.print(&cx.cache))));
// FIXME(camelid): I hope passing 0 as the depth doesn't break anything....
// Then again, I think used to be 0 anyway through CURRENT_DEPTH
// because (I think) rendering hadn't started yet.
return Generic(Symbol::intern(&format!("{:#}", path.print(&cx.cache, 0))));
Copy link
Member

@jyn514 jyn514 Mar 5, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change makes me nervous, can you say why you think rendering hadn't started?

I don't know exactly when this path is hit, path.segment.len() == 1 seems really strange because it doesn't leave any space for the crate name and I don't see any other reason to special case 1 path segment. Maybe add an unconditional panic!() so we have a test case?

@@ -170,6 +170,10 @@ crate struct SharedContext<'tcx> {
}

impl<'tcx> Context<'tcx> {
fn depth(&self) -> usize {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you wanted me to put docs on this; leaving a comment so I don't forget.

@camelid camelid force-pushed the current_depth-pt2 branch from 806fec1 to bf37b68 Compare March 5, 2021 22:30
@camelid
Copy link
Member Author

camelid commented Mar 5, 2021

Oh no, massive merge conflicts 😅

@camelid camelid force-pushed the current_depth-pt2 branch from bf37b68 to 4747a74 Compare March 5, 2021 22:41
@camelid
Copy link
Member Author

camelid commented Mar 5, 2021

Doing rebase in multiple parts to make it easier—first part done.

@camelid camelid force-pushed the current_depth-pt2 branch from 4747a74 to 49879e3 Compare March 6, 2021 00:11
@camelid
Copy link
Member Author

camelid commented Mar 6, 2021

Finished rebasing. Phew, that was probably one of the hardest rebases I've ever done 😅

@camelid
Copy link
Member Author

camelid commented Mar 6, 2021

Still need to squash my "fmt" commit.

@camelid camelid force-pushed the current_depth-pt2 branch from 49879e3 to 3057e4b Compare March 6, 2021 00:50
@camelid
Copy link
Member Author

camelid commented Mar 6, 2021

I formatted each commit individually and dropped the fmt commit. Should be ready to review now!

Comment on lines -219 to +220
tr.print(&self.ctx.cache),
impl_.for_.print(&self.ctx.cache),
tr.print(&self.ctx.cache, 0),
impl_.for_.print(&self.ctx.cache, 0),
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used 0 here because this is just for debug output.

debug!("impl {:#} in {}", impl_.for_.print(&self.ctx.cache), filename);
debug!("impl {:#} in {}", impl_.for_.print(&self.ctx.cache, 0), filename);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above.

@bors

This comment has been minimized.

@camelid camelid added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Mar 6, 2021
camelid added 4 commits March 5, 2021 18:57
This part actually wasn't that hard. Ending the use of it in
`html/format.rs` is probably going to be *a lot* harder.
@camelid camelid force-pushed the current_depth-pt2 branch from 3057e4b to 0e1ff40 Compare March 6, 2021 03:03
@camelid camelid removed the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Mar 6, 2021
@camelid
Copy link
Member Author

camelid commented Mar 6, 2021

Rebased. Apparently this is even more conflict-prone than I expected!

@camelid camelid added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Mar 11, 2021
@bors
Copy link
Contributor

bors commented Mar 22, 2021

☔ The latest upstream changes (presumably #82855) made this pull request unmergeable. Please resolve the merge conflicts.

@camelid camelid added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Mar 22, 2021
@jyn514
Copy link
Member

jyn514 commented Mar 24, 2021

AFAIK, this is waiting on:

  1. Remove CURRENT_DEPTH thread-local variable #82815 (review)
  2. Remove CURRENT_DEPTH thread-local variable #82815 (comment)
  3. Remove CURRENT_DEPTH thread-local variable #82815 (comment)
  4. and (optionally) Remove CURRENT_DEPTH thread-local variable #82815 (comment)

I would prefer to hear a response to 1 before spending too much more time on this; the rest I can ignore for now while reviewing.

@jyn514 jyn514 removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Mar 24, 2021
@camelid
Copy link
Member Author

camelid commented Mar 25, 2021

Can you point to where the depth is incremented and decremented?

Where the depth used to be changed or where it is changed now? Or both?

@camelid
Copy link
Member Author

camelid commented Mar 29, 2021

The old CURRENT_DEPTH variable used to be updated in two spots. The first one is here:

// A little unfortunate that this is done like this, but it sure
// does make formatting *a lot* nicer.
CURRENT_DEPTH.with(|slot| {
slot.set(self.current.len());
});

In this spot, it's being updated right before rendering an item, and it's set to the current length of the self.current variable. As I understand it, self.current looks like ["std", "io"]—it's a list of module path segments that we use for links.

self.current is updated here:

self.current.push(item_name.to_owned());

and here:

self.current.pop();


The other place at which CURRENT_DEPTH was updated is here:

CURRENT_DEPTH.with(|s| s.set(0));

This reset is necessary, even though CURRENT_DEPTH is initialized to Cell::new(0), because it is global mutable state that is shared with other Contexts, which may be at a different depth than the current Context.


In the new code (without CURRENT_DEPTH), we update self.current in the same places, and the only change is that we no longer update CURRENT_DEPTH (because it doesn't exist!).

@camelid
Copy link
Member Author

camelid commented Mar 29, 2021

Marking as waiting-on-review even though there are conflicts, because they are probably very mechanical to fix and it's probably easier to fix them all at the end or close to the end.

@camelid camelid added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Mar 29, 2021
@jyn514
Copy link
Member

jyn514 commented Apr 5, 2021

FYI I plan to review/merge #83237 before this PR, so it's fine not to fix conflicts until then.

@jyn514 jyn514 added S-blocked Status: Blocked on something else such as an RFC or other implementation work. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Apr 5, 2021
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this pull request Apr 17, 2021
rustdoc: use more precise relative URLs

This is a fairly large diff, and will probably conflict with rust-lang#82815 since it reduces (but does not eliminate) the use of the old depth variable.

Instead of using a depth counter and adding "../" to get to the top, this commit makes rustdoc actually compare the path of what it's linking from to the path that it's linking to. This makes the resulting HTML shorter.

Here's a comparison of one of the largest (non-source) files in the Rust standard library docs (about 4% improvement before gzipping).

    $ wc -c struct.Wrapping.old.html struct.Wrapping.new.html
    2387389 struct.Wrapping.old.html
    2298538 struct.Wrapping.new.html

Most if it can be efficiently gzipped away.

    $ wc -c struct.Wrapping.old.html.gz struct.Wrapping.new.html.gz
    70679 struct.Wrapping.old.html.gz
    70050 struct.Wrapping.new.html.gz

But it also makes a difference in the final DOM size, reducing it from 91MiB to 82MiB.
@jyn514
Copy link
Member

jyn514 commented Apr 18, 2021

Now that #83237 is merged, I think this approach is no longer necessary - CURRENT_DEPTH is only used for primitive_link and I would rather get rid of that rather than moving the depth into the cache (#83237 (comment)). I think @notriddle may be planning to work on that?

Sorry this won't be merged, I appreciate you putting in the time :)

@jyn514 jyn514 closed this Apr 18, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-cleanup Category: PRs that clean code up or issues documenting cleanup. S-blocked Status: Blocked on something else such as an RFC or other implementation work. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

rustdoc: Get rid of CURRENT_DEPTH thread-local variable
4 participants