diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs index 872770def1775..3c0a89b7c8a7f 100644 --- a/compiler/rustc_resolve/src/rustdoc.rs +++ b/compiler/rustc_resolve/src/rustdoc.rs @@ -393,13 +393,15 @@ pub fn has_primitive_or_keyword_or_attribute_docs(attrs: &[impl AttributeExt]) - } /// Simplified version of the corresponding function in rustdoc. -/// If the rustdoc version returns a successful result, this function must return the same result. -/// Otherwise this function may return anything. fn preprocess_link(link: &str) -> Box { + // IMPORTANT: To be kept in sync with the corresponding function in rustdoc. + // Namely, whenever the rustdoc function returns a successful result for a given input, + // this function *MUST* return a link that's equal to `PreprocessingInfo.path_str`! + let link = link.replace('`', ""); let link = link.split('#').next().unwrap(); let link = link.trim(); - let link = link.rsplit('@').next().unwrap(); + let link = link.split_once('@').map_or(link, |(_, rhs)| rhs); let link = link.trim_suffix("()"); let link = link.trim_suffix("{}"); let link = link.trim_suffix("[]"); diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index e29256bb5d1a5..ba1eb07d365ba 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -938,14 +938,18 @@ pub(crate) struct PreprocessedMarkdownLink( /// Returns: /// - `None` if the link should be ignored. -/// - `Some(Err)` if the link should emit an error -/// - `Some(Ok)` if the link is valid +/// - `Some(Err(_))` if the link should emit an error +/// - `Some(Ok(_))` if the link is valid /// /// `link_buffer` is needed for lifetime reasons; it will always be overwritten and the contents ignored. fn preprocess_link( ori_link: &MarkdownLink, dox: &str, ) -> Option> { + // IMPORTANT: To be kept in sync with the corresponding function in `rustc_resolve::rustdoc`. + // Namely, whenever this function returns a successful result for a given input, + // the rustc counterpart *MUST* return a link that's equal to `PreprocessingInfo.path_str`! + // certain link kinds cannot have their path be urls, // so they should not be ignored, no matter how much they look like urls. // e.g. [https://example.com/] is not a link to example.com. diff --git a/tests/rustdoc-ui/intra-doc/empty-associated-items.rs b/tests/rustdoc-ui/intra-doc/empty-associated-items.rs deleted file mode 100644 index ea94cb349ad29..0000000000000 --- a/tests/rustdoc-ui/intra-doc/empty-associated-items.rs +++ /dev/null @@ -1,8 +0,0 @@ -// This test ensures that an empty associated item will not crash rustdoc. -// This is a regression test for . - -#[deny(rustdoc::broken_intra_doc_links)] - -/// [`String::`] -//~^ ERROR -pub struct Foo; diff --git a/tests/rustdoc-ui/intra-doc/malformed-paths.rs b/tests/rustdoc-ui/intra-doc/malformed-paths.rs new file mode 100644 index 0000000000000..1f08d6d8efca9 --- /dev/null +++ b/tests/rustdoc-ui/intra-doc/malformed-paths.rs @@ -0,0 +1,17 @@ +// This test ensures that (syntactically) malformed paths will not crash rustdoc. +#![deny(rustdoc::broken_intra_doc_links)] + +// This is a regression test for . +//! [`Type::`] +//~^ ERROR + +// This is a regression test for . +//! [`struct@Type@field`] +//~^ ERROR + +//! [Type&content] +//~^ ERROR +//! [`Type::field%extra`] +//~^ ERROR + +pub struct Type { pub field: () } diff --git a/tests/rustdoc-ui/intra-doc/malformed-paths.stderr b/tests/rustdoc-ui/intra-doc/malformed-paths.stderr new file mode 100644 index 0000000000000..d38e7c2a73e48 --- /dev/null +++ b/tests/rustdoc-ui/intra-doc/malformed-paths.stderr @@ -0,0 +1,36 @@ +error: unresolved link to `Type::` + --> $DIR/malformed-paths.rs:5:7 + | +LL | //! [`Type::`] + | ^^^^^^ the struct `Type` has no field or associated item named `` + | +note: the lint level is defined here + --> $DIR/malformed-paths.rs:2:9 + | +LL | #![deny(rustdoc::broken_intra_doc_links)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: unresolved link to `Type@field` + --> $DIR/malformed-paths.rs:9:7 + | +LL | //! [`struct@Type@field`] + | ^^^^^^^^^^^^^^^^^ no item named `Type@field` in scope + | + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` + +error: unresolved link to `Type&content` + --> $DIR/malformed-paths.rs:12:6 + | +LL | //! [Type&content] + | ^^^^^^^^^^^^ no item named `Type&content` in scope + | + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` + +error: unresolved link to `Type::field%extra` + --> $DIR/malformed-paths.rs:14:7 + | +LL | //! [`Type::field%extra`] + | ^^^^^^^^^^^^^^^^^ the struct `Type` has no field or associated item named `field%extra` + +error: aborting due to 4 previous errors +