diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs index 970d16313584e..97283a0049e2c 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 the same result! + 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.strip_suffix("()").unwrap_or(link); let link = link.strip_suffix("{}").unwrap_or(link); let link = link.strip_suffix("[]").unwrap_or(link); diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index d09949e6868d6..04b3b503cc117 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 successfully returns a preprocessed link for a given input, + // the rustc counterpart *MUST* return the same link! + // 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..5139e42e966c6 --- /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 +