Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 35 additions & 23 deletions src/librustdoc/html/highlight.rs
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ struct TokenHandler<'a, 'tcx, F: Write> {
/// We need to keep the `Class` for each element because it could contain a `Span` which is
/// used to generate links.
href_context: Option<HrefContext<'a, 'tcx>>,
write_line_number: fn(u32) -> String,
line_number_kind: LineNumberKind,
line: u32,
max_lines: u32,
}
Expand All @@ -355,10 +355,10 @@ impl<F: Write> std::fmt::Debug for TokenHandler<'_, '_, F> {
}

impl<'a, F: Write> TokenHandler<'a, '_, F> {
fn handle_backline(&mut self) -> Option<String> {
fn handle_backline(&mut self) -> Option<impl Display + use<F>> {
self.line += 1;
if self.line < self.max_lines {
return Some((self.write_line_number)(self.line));
return Some(self.line_number_kind.render(self.line));
}
None
}
Expand All @@ -376,8 +376,7 @@ impl<'a, F: Write> TokenHandler<'a, '_, F> {
if text == "\n"
&& let Some(backline) = self.handle_backline()
{
self.out.write_str(&text).unwrap();
self.out.write_str(&backline).unwrap();
write!(self.out, "{text}{backline}").unwrap();
} else {
self.push_token_without_backline_check(class, text, true);
}
Expand Down Expand Up @@ -437,20 +436,29 @@ impl<F: Write> Drop for TokenHandler<'_, '_, F> {
}
}

fn scraped_line_number(line: u32) -> String {
// https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag#data-nosnippet-attr
// Do not show "1 2 3 4 5 ..." in web search results.
format!("<span data-nosnippet>{line}</span>")
}

fn line_number(line: u32) -> String {
// https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag#data-nosnippet-attr
// Do not show "1 2 3 4 5 ..." in web search results.
format!("<a href=#{line} id={line} data-nosnippet>{line}</a>")
/// Represents the type of line number to be generated as HTML.
#[derive(Clone, Copy)]
enum LineNumberKind {
/// Used for scraped code examples.
Scraped,
/// Used for source code pages.
Normal,
/// Code examples in documentation don't have line number generated by rustdoc.
Empty,
}

fn empty_line_number(_: u32) -> String {
String::new()
impl LineNumberKind {
fn render(self, line: u32) -> impl Display {
fmt::from_fn(move |f| {
match self {
// https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag#data-nosnippet-attr
// Do not show "1 2 3 4 5 ..." in web search results.
Self::Scraped => write!(f, "<span data-nosnippet>{line}</span>"),
Self::Normal => write!(f, "<a href=#{line} id={line} data-nosnippet>{line}</a>"),
Self::Empty => Ok(()),
}
})
}
}

fn get_next_expansion(
Expand Down Expand Up @@ -534,15 +542,15 @@ pub(super) fn write_code(
let mut token_handler = TokenHandler {
out,
href_context,
write_line_number: match line_info {
line_number_kind: match line_info {
Some(line_info) => {
if line_info.is_scraped_example {
scraped_line_number
LineNumberKind::Scraped
} else {
line_number
LineNumberKind::Normal
}
}
None => empty_line_number,
None => LineNumberKind::Empty,
},
line: 0,
max_lines: u32::MAX,
Expand All @@ -552,8 +560,12 @@ pub(super) fn write_code(
if let Some(line_info) = line_info {
token_handler.line = line_info.start_line - 1;
token_handler.max_lines = line_info.max_lines;
if let Some(text) = token_handler.handle_backline() {
token_handler.push_token_without_backline_check(None, Cow::Owned(text), false);
if let Some(backline) = token_handler.handle_backline() {
token_handler.push_token_without_backline_check(
None,
Cow::Owned(backline.to_string()),
Copy link
Contributor

Choose a reason for hiding this comment

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

The fact that we're using Cow::Owned here didn't sit right to me, so I did some digging and found out push_token_without_backline_check has overly restrictive lifetimes. It should use text: Cow<'_, str>, not text: Cow<'a, str>.

Actually, I think it could even be just text: &str, since it doesn't look like the code ever takes advantage of the Owned case and instead just uses it as impl Display, but that would require more refactoring than just changing a lifetime

Copy link
Member Author

Choose a reason for hiding this comment

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

backline is a LineNumber, so we need to convert it to something compatible.

Copy link
Contributor

Choose a reason for hiding this comment

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

I mean, I think impl Display would also work? not sure the monomorphization would be worth it, could maybe experiment in a follow-up PR.

Regardless, the lifetime still is overly restrictive, and it's hard to see that as anything but a mistake.

Copy link
Member Author

Choose a reason for hiding this comment

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

Hum, might be worth trying in a follow-up.

false,
);
}
}

Expand Down
Loading