Rollup merge of #55962 - QuietMisdreavus:tricky-spans, r=GuillaumeGomez

rustdoc: properly calculate spans for intra-doc link resolution errors

Fixes https://github.com/rust-lang/rust/issues/55723

When rustdoc is reporting a resolution error for intra-doc links, it needs to convert a span from one relative to the *markdown* (as the links are only found on the final markdown text) to one relative to the *source code* (as the error reporting is meant to show where the line is in the source, so the user can fix it). However, a calculation for how much "offset" to apply had a subtle error: it trimmed the whole line when attempting to account for leading indentation. This caused it to add in *trailing* whitespace into this calculation, which created an incorrect span.

In a lot of situations, this isn't a problem - the span will be shifted in the code slightly, but the warning will still be displayed and mostly legible. However, there is one important situation where this can cause an ICE: multi-byte codepoints. If a shifted span now has a starting point in the middle of a multi-byte codepoint, libsyntax will panic when trying to track what source item it corresponds to. This flew under our radar because trailing whitespace and multi-byte codepoints are both situations that we don't run into in the compiler repo.

(There is one more situation where this can error, that will be much harder to fix: block-style doc comments. Lines in a block-style doc comment have a zero-or-more (usually one) character offset per line, causing this calculation to be way off. I'm punting that to another issue, though...)
This commit is contained in:
Pietro Albini 2018-11-18 23:24:49 +01:00 committed by kennytm
commit f13d16621e
No known key found for this signature in database
GPG Key ID: FEF6C8051D0E013C
3 changed files with 38 additions and 1 deletions

View File

@ -527,7 +527,7 @@ fn resolution_failure(
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()
sum + doc_comment_padding + line.len() - line.trim_start().len()
})
};

View File

@ -0,0 +1,24 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-tidy-end-whitespace
#![deny(intra_doc_link_resolution_failure)]
// An error in calculating spans while reporting intra-doc link resolution errors caused rustdoc to
// attempt to slice in the middle of a multibyte character. See
// https://github.com/rust-lang/rust/issues/55723
/// ## For example:
///
/// arr[i]
pub fn test_ice() {
unimplemented!();
}

View File

@ -0,0 +1,13 @@
error: `[i]` cannot be resolved, ignoring it...
--> $DIR/intra-link-span-ice-55723.rs:21:10
|
LL | /// arr[i]
| ^ cannot be resolved, ignoring
|
note: lint level defined here
--> $DIR/intra-link-span-ice-55723.rs:13:9
|
LL | #![deny(intra_doc_link_resolution_failure)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]`