Skip to content

rustdoc: intra-doc link errors give incorrect spans on certain block doc comments #55964

Closed
@QuietMisdreavus

Description

@QuietMisdreavus

Given the following source:

/** # for example,
 *
 * time to introduce a link [error]*/
pub struct SomeStruct;

The span conversion calculation in the error reporting will give the wrong offset when reporting the resolution failure, leading to a confusing report:

$ cargo +nightly doc
 Documenting asdf v0.1.0 (/home/misdreavus/git/asdf)
warning: `[error]` cannot be resolved, ignoring it...
 --> src/lib.rs:3:33
  |
3 |   time to introduce a link [error]*/
  |  _________________________________^
4 | | pub struct SomeStruct;
  | |__^ cannot be resolved, ignoring
  |
  = note: #[warn(intra_doc_link_resolution_failure)] on by default
  = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`

    Finished dev [unoptimized + debuginfo] target(s) in 2.12s

Strangely enough, putting either the leading /** or the closing */ on its own line will cause the report to change to something that looks correct, if a little too broad:

/**
 * # for example,
 *
 * time to introduce a link [error]
 */
pub struct SomeStruct;
$ cargo +nightly doc
 Documenting asdf v0.1.0 (/home/misdreavus/git/asdf)
warning: `[error]` cannot be resolved, ignoring it...
 --> src/lib.rs:1:1
  |
1 | / /**
2 | |  * # for example,
3 | |  *
4 | |  * time to introduce a link [error]
5 | |  */
  | |___^
  |
  = note: #[warn(intra_doc_link_resolution_failure)] on by default
  = note: the link appears in this line:

           time to introduce a link [error]
                                     ^^^^^
  = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`

    Finished dev [unoptimized + debuginfo] target(s) in 2.12s

I believe the code at fault is this section here:

let line_offset = dox[..link_range.start].lines().count();
// The span starts in the `///`, so we don't have to account for the leading whitespace
let code_dox_len = if line_offset <= 1 {
doc_comment_padding
} else {
// The first `///`
doc_comment_padding +
// Each subsequent leading whitespace and `///`
code_dox.lines().skip(1).take(line_offset - 1).fold(0, |sum, line| {
sum + doc_comment_padding + line.len() - line.trim().len()
})
};
// Extract the specific span
let sp = sp.from_inner_byte_pos(
link_range.start + code_dox_len,
link_range.end + code_dox_len,
);

Because it assumes that every doc comment will have a padding of 3 characters (the /// or //!), it includes that in its calculation of each line's offset. However, for block-style comments, this assumption is false.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-intra-doc-linksArea: Intra-doc links, the ability to link to items in docs by nameT-rustdocRelevant to the rustdoc team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions