Skip to content

Conversation

@GuillaumeGomez
Copy link
Member

This is the bug uncovered in #150022. Once fixed Ill rebuild all compiler docs and see if we can enable the option for compiler docs. =D

It's a weird case where we extracted some tokens out of the iterator and then, when checking next items (from this iterator), it didn't find the : token, and therefore badly assumed the token kind.

The solution I came up with is to instead not extract tokens from the iterator and to count how many tokens are in the current path. So when iterate over the items, instead of having a mix of extracted tokens and tokens still inside the iterator, we now only iterate over the iterator.

The biggest change here is that get_full_ident_path will return an option instead of a Vec, and if it's contains : (one, not two), then it will return None and the : will be handled like any token and not like a path (which is more correct imo).

r? @yotamofek

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. 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. labels Dec 17, 2025
.copied()
}

fn peek_next_if<F: Fn((TokenKind, &'a str)) -> bool>(
Copy link
Member Author

Choose a reason for hiding this comment

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

So in case we don't find the item we're interested in, we don't want the item to impact the "peeked" items position, so I needed to write this function to "put back the item" in case it didn't match the condition.

Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder if it would make sense to switch the implementation of peek_next and peek_next_if around, and then implement peek_next in terms of peek_next_if(|_| true).

Copy link
Member Author

Choose a reason for hiding this comment

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

Huuuum... I see your point but I tend to prefer to have the "call-less"/simpler function as core and then build on top of it. I think it's the "personal taste" area in here. 😆

for _ in 0..nb_items {
if let Some((_, text, _)) = classifier.next() {
len += text.len();
}
Copy link
Member Author

Choose a reason for hiding this comment

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

Code doesn't need this continue anymore and that makes it much simpler to understand (so yeah, kinda congratulating myself here ^^').

Copy link
Contributor

Choose a reason for hiding this comment

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

This is much better 😁

let mut nb_items = 0;

loop {
let ret = loop {
Copy link
Member Author

Choose a reason for hiding this comment

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

We don't return in this loop because we need to call stop_peeking before exiting this function. So instead, we break the value to return, call stop_peeking and then actually return. Not super graceful but it works.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, would be nice to be able to just use return but also call stop_peeking() indiscriminately. Oh well... maybe in a future PR.

Copy link
Member Author

Choose a reason for hiding this comment

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

Well we could but then the whole loop content needs to be in another function. Then it's basically a debate over personal taste. ^^'

@yotamofek
Copy link
Contributor

yotamofek commented Dec 17, 2025

The change makes sense, and all the tests plus the new one pass, so I'm inclined to just accept it as-is, without diving too deep into this. The highlighting code is quite complex and I'm more reliant on tests than my ability to run the code in my head.

So r+ from me if you want to get this in, we can always make improvements later. If it's not urgent then give me a few more days to spend some quality time with this. Up to you :)

Comment on lines 924 to 929
let mut len = 0;
for _ in 0..nb_items {
if let Some((_, text, _)) = classifier.next() {
len += text.len();
}
}
Copy link
Contributor

@yotamofek yotamofek Dec 17, 2025

Choose a reason for hiding this comment

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

Suggested change
let mut len = 0;
for _ in 0..nb_items {
if let Some((_, text, _)) = classifier.next() {
len += text.len();
}
}
let len: usize = iter::from_fn(|| classifier.next())
.take(nb_items)
.map(|(_, text, _)| text.len())
.sum();

Take it or leave it:

I know you're not a big fan of iterator combinators and the functional style, but I think that apart from being more readable (IMHO, of course), this also has an additional benefit that it'll stop calling classifier.next() after the first None, even if it yields less than nb_items items :)

Copy link
Member Author

Choose a reason for hiding this comment

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

In this case I like it. ;)

@GuillaumeGomez
Copy link
Member Author

@yotamofek: Gonna go ahead and approve it. I implemented your suggestion for the iterator. I'm looking forward to which improvements you will come up with next. :)

@bors r=yotamofek rollup

@bors
Copy link
Collaborator

bors commented Dec 17, 2025

📌 Commit 2114b21 has been approved by yotamofek

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Dec 17, 2025
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Dec 17, 2025
…otamofek

[rustdoc] Fix invalid handling of field followed by negated macro call

This is the bug uncovered in rust-lang#150022. Once fixed Ill rebuild all compiler docs and see if we can enable the option for compiler docs. =D

It's a weird case where we extracted some tokens out of the iterator and then, when checking next items (from this iterator), it didn't find the `:` token, and therefore badly assumed the token kind.

The solution I came up with is to instead not extract tokens from the iterator and to count how many tokens are in the current path. So when iterate over the items, instead of having a mix of extracted tokens and tokens still inside the iterator, we now only iterate over the iterator.

The biggest change here is that `get_full_ident_path` will return an option instead of a `Vec`, and if it's contains `:` (one, not two), then it will return `None` and the `:` will be handled like any token and not like a path (which is more correct imo).

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

Labels

S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. 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