diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index baa9fddc2a651..5fd632f9b000f 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2302,7 +2302,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { self.check_param_uses_if_mcg(ct, tcx.hir_span(path_hir_id), false) } - /// Lower a [`hir::ConstArg`] to a (type-level) [`ty::Const`](Const). + /// Lower a [`hir::ConstArg`] to a (type-level) [`ty::Const`]. #[instrument(skip(self), level = "debug")] pub fn lower_const_arg(&self, const_arg: &hir::ConstArg<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> { let tcx = self.tcx(); diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs index 92bc577f59201..ddf5600f76659 100644 --- a/compiler/rustc_resolve/src/rustdoc.rs +++ b/compiler/rustc_resolve/src/rustdoc.rs @@ -641,42 +641,99 @@ pub fn source_span_for_markdown_range_inner( let mut start_bytes = 0; let mut end_bytes = 0; + let span_of_all_fragments: Span = span_of_fragments(fragments)?; + + let mut prev_lines_bytes = 0; 'outer: for (line_no, md_line) in md_lines.enumerate() { loop { let source_line = src_lines.next()?; - match source_line.find(md_line) { - Some(offset) => { - if line_no == starting_line { - start_bytes += offset; + let source_line_len = u32::try_from(source_line.len()).unwrap(); + let source_line_span = + span_of_all_fragments.split_at(prev_lines_bytes).1.split_at(source_line_len).0; + let fragment = fragments + .iter() + // `source_line_span` might contain indentation that `fragment.span` doesn't contain + .find(|fragment| fragment.span.overlaps(source_line_span)); + // Since we're counting bytes, `prev_line_bytes` includes the "\n". + prev_lines_bytes += source_line_len + 1; + if let Some(fragment) = fragment + && let Some(offset) = source_line.find(md_line) + { + if fragment.span.lo() > source_line_span.lo() + && source_line + [..usize::try_from(fragment.span.lo().0 - source_line_span.lo().0).unwrap()] + .chars() + .any(|c| !c.is_whitespace()) + { + // Make sure anything between the start of this line and the fragment itself is just indentation. + // Because source_line is built by splitting the span that covers all fragments, this only finds + // characters *between* doc comments, not characters before or after doc comments. + // + // 1| /** doc */ + // 2| #[inline] /** doc2 */ + // ^^^^^^^^^ + // | this + // + // 3| fn foo() {} + return None; + } + if fragment.span.hi() < source_line_span.hi() + && source_line + [usize::try_from(fragment.span.hi().0 - source_line_span.lo().0).unwrap()..] + .chars() + .any(|c| !c.is_whitespace()) + { + // Make sure anything between the start of this line and the fragment itself is just indentation. + // Because source_line is built by splitting the span that covers all fragments, this only finds + // characters *between* doc comments, not characters before or after doc comments. + // 1| /** doc */ #[inline] + // ^^^^^^^^^ + // | this + // + // 2| /** doc2 */ + // 3| fn foo() {} + return None; + } + if line_no == starting_line { + start_bytes += offset; - if starting_line == ending_line { - break 'outer; - } - } else if line_no == ending_line { - end_bytes += offset; + if starting_line == ending_line { break 'outer; - } else if line_no < starting_line { - start_bytes += source_line.len() - md_line.len(); - } else { - end_bytes += source_line.len() - md_line.len(); } - break; + } else if line_no == ending_line { + end_bytes += offset; + break 'outer; + } else if line_no < starting_line { + start_bytes += source_line.len() - md_line.len(); + } else { + end_bytes += source_line.len() - md_line.len(); } - None => { - // Since this is a source line that doesn't include a markdown line, - // we have to count the newline that we split from earlier. - if line_no <= starting_line { - start_bytes += source_line.len() + 1; - } else { - end_bytes += source_line.len() + 1; - } + break; + } else { + // Since this is a source line that doesn't include a markdown line, + // we have to count it and its newline as non-markdown bytes. + if line_no <= starting_line { + start_bytes += source_line.len() + 1; + } else if source_line.chars().any(|c| !c.is_whitespace()) { + // We're past the first line, but haven't found the last line, + // but we found a non-empty non-markdown line. + // This could be an attribute, and we don't want a diagnostic + // suggesting to delete that attribute, so we return None to be safe. + // 1| /** doc */ + // 2 | #[inline] + // ^^^^^^^^^ + // | this + // 3| /** doc2 */ + // 4| fn foo() {} + return None; + } else { + end_bytes += source_line.len() + 1; } } } } - let span = span_of_fragments(fragments)?; - let src_span = span.from_inner(InnerSpan::new( + let src_span = span_of_all_fragments.from_inner(InnerSpan::new( md_range.start + start_bytes, md_range.end + start_bytes + end_bytes, )); diff --git a/src/librustdoc/passes/lint/redundant_explicit_links.rs b/src/librustdoc/passes/lint/redundant_explicit_links.rs index 8da21f100c6a3..cd7b7caac69ad 100644 --- a/src/librustdoc/passes/lint/redundant_explicit_links.rs +++ b/src/librustdoc/passes/lint/redundant_explicit_links.rs @@ -80,7 +80,7 @@ fn check_redundant_explicit_link<'md>( hir_id: HirId, doc: &'md str, resolutions: &DocLinkResMap, -) -> Option<()> { +) { let mut broken_line_callback = |link: BrokenLink<'md>| Some((link.reference, "".into())); let mut offset_iter = Parser::new_with_broken_link_callback( doc, @@ -115,7 +115,7 @@ fn check_redundant_explicit_link<'md>( } if dest_url.ends_with(resolvable_link) || resolvable_link.ends_with(&*dest_url) { - match link_type { + let check_result = match link_type { LinkType::Inline | LinkType::ReferenceUnknown => { check_inline_or_reference_unknown_redundancy( cx, @@ -127,27 +127,52 @@ fn check_redundant_explicit_link<'md>( dest_url.to_string(), link_data, if link_type == LinkType::Inline { (b'(', b')') } else { (b'[', b']') }, - ); - } - LinkType::Reference => { - check_reference_redundancy( - cx, - item, - hir_id, - doc, - resolutions, - link_range, - &dest_url, - link_data, - ); + ) } - _ => {} + LinkType::Reference => check_reference_redundancy( + cx, + item, + hir_id, + doc, + resolutions, + link_range, + &dest_url, + link_data, + ), + _ => Ok(()), + }; + if let Err(lint) = check_result { + cx.tcx.emit_node_span_lint( + crate::lint::REDUNDANT_EXPLICIT_LINKS, + hir_id, + item.attr_span(cx.tcx), + lint, + ); } } } } +} - None +struct RedundantExplicitLinksWithoutSuggestion { + attr_span: Span, + display_link: String, + dest_link: String, +} + +impl<'a> Diagnostic<'a, ()> for RedundantExplicitLinksWithoutSuggestion { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + let Self { attr_span, display_link, dest_link } = self; + + Diag::new(dcx, level, "redundant explicit link target") + .with_span_label( + attr_span, + format!("explicit target `{dest_link}` is redundant because label `{display_link}` resolves to same destination") + ) + .with_note( + "when a link's destination is not specified,\nthe label is used to resolve intra-doc links" + ) + } } /// FIXME(ChAoSUnItY): Too many arguments. @@ -161,7 +186,7 @@ fn check_inline_or_reference_unknown_redundancy( dest: String, link_data: LinkData, (open, close): (u8, u8), -) -> Option<()> { +) -> Result<(), RedundantExplicitLinksWithoutSuggestion> { struct RedundantExplicitLinks { explicit_span: Span, display_span: Span, @@ -196,42 +221,65 @@ fn check_inline_or_reference_unknown_redundancy( } } - let (resolvable_link, resolvable_link_range) = - (&link_data.resolvable_link?, &link_data.resolvable_link_range?); - let (dest_res, display_res) = - (find_resolution(resolutions, &dest)?, find_resolution(resolutions, resolvable_link)?); + let (Some(resolvable_link), Some(resolvable_link_range)) = + (&link_data.resolvable_link, &link_data.resolvable_link_range) + else { + return Ok(()); + }; + let (Some(dest_res), Some(display_res)) = + (find_resolution(resolutions, &dest), find_resolution(resolutions, resolvable_link)) + else { + return Ok(()); + }; if dest_res == display_res { + let attr_span = item.attr_span(cx.tcx); let link_span = match source_span_for_markdown_range(cx.tcx, doc, &link_range, &item.attrs.doc_strings) { Some((sp, from_expansion)) => { if from_expansion { - return None; + return Ok(()); } sp } - None => item.attr_span(cx.tcx), + None => attr_span, }; - let (explicit_span, false) = source_span_for_markdown_range( + let explicit_span = match source_span_for_markdown_range( cx.tcx, doc, &offset_explicit_range(doc, link_range, open, close), &item.attrs.doc_strings, - )? - else { + ) { + Some((explicit_span, false)) => explicit_span, // This `span` comes from macro expansion so skipping it. - return None; + Some((_, true)) => return Ok(()), + // Cannot give a contiguous span for this link. + None => { + return Err(RedundantExplicitLinksWithoutSuggestion { + display_link: resolvable_link.clone(), + dest_link: dest.to_string(), + attr_span, + }); + } }; - let (display_span, false) = source_span_for_markdown_range( + let display_span = match source_span_for_markdown_range( cx.tcx, doc, resolvable_link_range, &item.attrs.doc_strings, - )? - else { + ) { + Some((display_span, false)) => display_span, // This `span` comes from macro expansion so skipping it. - return None; + Some((_, true)) => return Ok(()), + // Cannot give a contiguous span for this link. + None => { + return Err(RedundantExplicitLinksWithoutSuggestion { + display_link: resolvable_link.clone(), + dest_link: dest.to_string(), + attr_span, + }); + } }; cx.tcx.emit_node_span_lint( @@ -247,7 +295,7 @@ fn check_inline_or_reference_unknown_redundancy( ); } - None + Ok(()) } /// FIXME(ChAoSUnItY): Too many arguments. @@ -260,7 +308,7 @@ fn check_reference_redundancy( link_range: Range, dest: &CowStr<'_>, link_data: LinkData, -) -> Option<()> { +) -> Result<(), RedundantExplicitLinksWithoutSuggestion> { struct RedundantExplicitLinkTarget { explicit_span: Span, display_span: Span, @@ -294,49 +342,83 @@ fn check_reference_redundancy( } } - let (resolvable_link, resolvable_link_range) = - (&link_data.resolvable_link?, &link_data.resolvable_link_range?); - let (dest_res, display_res) = - (find_resolution(resolutions, dest)?, find_resolution(resolutions, resolvable_link)?); + let (Some(resolvable_link), Some(resolvable_link_range)) = + (&link_data.resolvable_link, &link_data.resolvable_link_range) + else { + return Ok(()); + }; + let (Some(dest_res), Some(display_res)) = + (find_resolution(resolutions, dest), find_resolution(resolutions, resolvable_link)) + else { + return Ok(()); + }; if dest_res == display_res { + let attr_span = item.attr_span(cx.tcx); let link_span = match source_span_for_markdown_range(cx.tcx, doc, &link_range, &item.attrs.doc_strings) { Some((sp, from_expansion)) => { if from_expansion { - return None; + // This `span` comes from macro expansion so skipping it. + return Ok(()); } sp } - None => item.attr_span(cx.tcx), + None => attr_span, }; - let (explicit_span, false) = source_span_for_markdown_range( + let explicit_span = match source_span_for_markdown_range( cx.tcx, doc, &offset_explicit_range(doc, link_range.clone(), b'[', b']'), &item.attrs.doc_strings, - )? - else { + ) { + Some((explicit_span, false)) => explicit_span, // This `span` comes from macro expansion so skipping it. - return None; + Some((_, true)) => return Ok(()), + // Cannot give a contiguous span for this link. + None => { + return Err(RedundantExplicitLinksWithoutSuggestion { + display_link: resolvable_link.clone(), + dest_link: dest.to_string(), + attr_span, + }); + } }; - let (display_span, false) = source_span_for_markdown_range( + let display_span = match source_span_for_markdown_range( cx.tcx, doc, resolvable_link_range, &item.attrs.doc_strings, - )? - else { + ) { + Some((display_span, false)) => display_span, // This `span` comes from macro expansion so skipping it. - return None; + Some((_, true)) => return Ok(()), + // Cannot give a contiguous span for this link. + None => { + return Err(RedundantExplicitLinksWithoutSuggestion { + display_link: resolvable_link.clone(), + dest_link: dest.to_string(), + attr_span, + }); + } }; - let (def_span, _) = source_span_for_markdown_range( + let def_span = match source_span_for_markdown_range( cx.tcx, doc, &offset_reference_def_range(doc, dest, link_range), &item.attrs.doc_strings, - )?; + ) { + Some((def_span, _)) => def_span, + // Cannot give a contiguous span for this link. + None => { + return Err(RedundantExplicitLinksWithoutSuggestion { + display_link: resolvable_link.clone(), + dest_link: dest.to_string(), + attr_span, + }); + } + }; cx.tcx.emit_node_span_lint( crate::lint::REDUNDANT_EXPLICIT_LINKS, @@ -352,7 +434,7 @@ fn check_reference_redundancy( ); } - None + Ok(()) } fn find_resolution(resolutions: &DocLinkResMap, path: &str) -> Option> { diff --git a/src/tools/clippy/clippy_lints/src/doc/mod.rs b/src/tools/clippy/clippy_lints/src/doc/mod.rs index c5816cb8b2d63..013fb32bdaf3c 100644 --- a/src/tools/clippy/clippy_lints/src/doc/mod.rs +++ b/src/tools/clippy/clippy_lints/src/doc/mod.rs @@ -1242,7 +1242,8 @@ fn check_doc<'a, Events: Iterator, Range, Range tests/ui/doc/unbalanced_ticks.rs:6:5 + --> tests/ui/doc/unbalanced_ticks.rs:6:1 | -LL | /// This is a doc comment with `unbalanced_tick marks and several words that - | _____^ +LL | / /// This is a doc comment with `unbalanced_tick marks and several words that LL | | LL | | /// should be `encompassed_by` tick marks because they `contain_underscores`. LL | | /// Because of the initial `unbalanced_tick` pair, the error message is diff --git a/tests/rustdoc-ui/lints/invalid-html-tags-ice-146890.rs b/tests/rustdoc-ui/lints/invalid-html-tags-ice-146890.rs index d7efc201e7e39..53df3e9eb5a80 100644 --- a/tests/rustdoc-ui/lints/invalid-html-tags-ice-146890.rs +++ b/tests/rustdoc-ui/lints/invalid-html-tags-ice-146890.rs @@ -7,17 +7,17 @@ /// /// key +//~^^ ERROR: unclosed HTML tag `TH` /// +//~^^ ERROR: unopened HTML tag `TD` /// value +//~^^ ERROR: unclosed HTML tag `TH` /// +//~^^ ERROR: unopened HTML tag `TD` /// /// | |_____^ | @@ -18,7 +17,6 @@ error: unopened HTML tag `TD` | LL | /// | |_____^ diff --git a/tests/rustdoc-ui/lints/invalid-html-tags.rs b/tests/rustdoc-ui/lints/invalid-html-tags.rs index 8003e5efdd582..f5700e5846e51 100644 --- a/tests/rustdoc-ui/lints/invalid-html-tags.rs +++ b/tests/rustdoc-ui/lints/invalid-html-tags.rs @@ -164,8 +164,8 @@ pub fn r() {} /// >
/// > href="#broken" +//~^^ ERROR incomplete HTML tag `img` pub fn s() {} ///
diff --git a/tests/rustdoc-ui/lints/invalid-html-tags.stderr b/tests/rustdoc-ui/lints/invalid-html-tags.stderr index b6ec22c247901..3256004ddb6ab 100644 --- a/tests/rustdoc-ui/lints/invalid-html-tags.stderr +++ b/tests/rustdoc-ui/lints/invalid-html-tags.stderr @@ -123,7 +123,6 @@ error: incomplete HTML tag `img` | LL | /// > href="#broken" | |____________________^ diff --git a/tests/rustdoc-ui/lints/redundant_explicit_links_split.rs b/tests/rustdoc-ui/lints/redundant_explicit_links_split.rs new file mode 100644 index 0000000000000..eebc6a0aa023c --- /dev/null +++ b/tests/rustdoc-ui/lints/redundant_explicit_links_split.rs @@ -0,0 +1,100 @@ +#![deny(rustdoc::redundant_explicit_links)] +use std::clone::Clone; + +/// [Clone]( +pub fn split_outer_inner() { + //! std::clone::Clone) +//~^^^ ERROR redundant_explicit_links +} + +/// [Clone](std::clone::Clone +pub fn split_outer_inner_b() { + //! ) +//~^^^ ERROR redundant_explicit_links +} + +/// [Clone]( +#[inline] +/// std::clone::Clone) +//~^^^ ERROR redundant_explicit_links +pub fn split_attr() { +} + +/// [Clone](std::clone::Clone +#[inline] +/// ) +//~^^^ ERROR redundant_explicit_links +pub fn split_attr_b() { +} + +/** [Clone]( */ #[inline] /** std::clone::Clone) */ +//~^ ERROR redundant_explicit_links +pub fn split_blockcomment_attr() { +} + +/** [Clone](std::clone::Clone */ #[inline] /** ) */ +//~^ ERROR redundant_explicit_links +pub fn split_blockcomment_attr_b() { +} + +/** [Clone]( */ +#[inline] +/** std::clone::Clone) */ +//~^^^ ERROR redundant_explicit_links +pub fn split_blockcomment_multiline_attr() { +} + +/** [Clone](std::clone::Clone */ +#[inline] +/** ) */ +//~^^^ ERROR redundant_explicit_links +pub fn split_blockcomment_multiline_attr_b() { +} + +/** [Clone]( */ #[inline] +/** std::clone::Clone) */ +//~^^ ERROR redundant_explicit_links +pub fn split_blockcomment_twoline_attr() { +} + +/** [Clone](std::clone::Clone */ #[inline] +/** ) */ +//~^^ ERROR redundant_explicit_links +pub fn split_blockcomment_twoline_attr_b() { +} + +/** [Clone]( */ +#[inline] /** std::clone::Clone) */ +//~^^ ERROR redundant_explicit_links +pub fn split_blockcomment_secondline_attr() { +} + +/** [Clone](std::clone::Clone */ +#[inline] /** ) */ +//~^^ ERROR redundant_explicit_links +pub fn split_blockcomment_secondline_attr_b() { +} + +/** [Clone](std::clone::Clone) */ #[inline] +//~^ ERROR redundant_explicit_links +//~| SUGGESTION [Clone] +pub fn split_blockcomment_singleline_attr() { +} + +/** [Clone](std::clone::Clone) */ #[inline] pub fn split_blockcomment_singleline_attr_b() { } +//~^ ERROR redundant_explicit_links +//~| SUGGESTION [Clone] + +/// [Clone]( +/// std::clone::Clone) +//~^^ ERROR redundant_explicit_links +//~| SUGGESTION [Clone] +pub fn not_split() { +} + +/// [Clone](std::clone::Clone +/// ) +//~^^ ERROR redundant_explicit_links +//~| SUGGESTION [Clone] +pub fn not_split_b() { +} diff --git a/tests/rustdoc-ui/lints/redundant_explicit_links_split.stderr b/tests/rustdoc-ui/lints/redundant_explicit_links_split.stderr new file mode 100644 index 0000000000000..bfab5b751eedf --- /dev/null +++ b/tests/rustdoc-ui/lints/redundant_explicit_links_split.stderr @@ -0,0 +1,201 @@ +error: redundant explicit link target + --> $DIR/redundant_explicit_links_split.rs:4:1 + | +LL | / /// [Clone]( +LL | | pub fn split_outer_inner() { +LL | | //! std::clone::Clone) + | |__________________________^ explicit target `std::clone::Clone` is redundant because label `Clone` resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +note: the lint level is defined here + --> $DIR/redundant_explicit_links_split.rs:1:9 + | +LL | #![deny(rustdoc::redundant_explicit_links)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links_split.rs:10:1 + | +LL | / /// [Clone](std::clone::Clone +LL | | pub fn split_outer_inner_b() { +LL | | //! ) + | |_________^ explicit target `std::clone::Clone` is redundant because label `Clone` resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links + +error: redundant explicit link target + --> $DIR/redundant_explicit_links_split.rs:16:1 + | +LL | / /// [Clone]( +LL | | #[inline] +LL | | /// std::clone::Clone) + | |______________________^ explicit target `std::clone::Clone` is redundant because label `Clone` resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links + +error: redundant explicit link target + --> $DIR/redundant_explicit_links_split.rs:23:1 + | +LL | / /// [Clone](std::clone::Clone +LL | | #[inline] +LL | | /// ) + | |_____^ explicit target `std::clone::Clone` is redundant because label `Clone` resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links + +error: redundant explicit link target + --> $DIR/redundant_explicit_links_split.rs:30:1 + | +LL | /** [Clone]( */ #[inline] /** std::clone::Clone) */ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ explicit target `std::clone::Clone` is redundant because label `Clone` resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links + +error: redundant explicit link target + --> $DIR/redundant_explicit_links_split.rs:35:1 + | +LL | /** [Clone](std::clone::Clone */ #[inline] /** ) */ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ explicit target `std::clone::Clone` is redundant because label `Clone` resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links + +error: redundant explicit link target + --> $DIR/redundant_explicit_links_split.rs:40:1 + | +LL | / /** [Clone]( */ +LL | | #[inline] +LL | | /** std::clone::Clone) */ + | |_________________________^ explicit target `std::clone::Clone` is redundant because label `Clone` resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links + +error: redundant explicit link target + --> $DIR/redundant_explicit_links_split.rs:47:1 + | +LL | / /** [Clone](std::clone::Clone */ +LL | | #[inline] +LL | | /** ) */ + | |________^ explicit target `std::clone::Clone` is redundant because label `Clone` resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links + +error: redundant explicit link target + --> $DIR/redundant_explicit_links_split.rs:54:1 + | +LL | / /** [Clone]( */ #[inline] +LL | | /** std::clone::Clone) */ + | |_________________________^ explicit target `std::clone::Clone` is redundant because label `Clone` resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links + +error: redundant explicit link target + --> $DIR/redundant_explicit_links_split.rs:60:1 + | +LL | / /** [Clone](std::clone::Clone */ #[inline] +LL | | /** ) */ + | |________^ explicit target `std::clone::Clone` is redundant because label `Clone` resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links + +error: redundant explicit link target + --> $DIR/redundant_explicit_links_split.rs:66:1 + | +LL | / /** [Clone]( */ +LL | | #[inline] /** std::clone::Clone) */ + | |___________________________________^ explicit target `std::clone::Clone` is redundant because label `Clone` resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links + +error: redundant explicit link target + --> $DIR/redundant_explicit_links_split.rs:72:1 + | +LL | / /** [Clone](std::clone::Clone */ +LL | | #[inline] /** ) */ + | |__________________^ explicit target `std::clone::Clone` is redundant because label `Clone` resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links + +error: redundant explicit link target + --> $DIR/redundant_explicit_links_split.rs:78:13 + | +LL | /** [Clone](std::clone::Clone) */ #[inline] + | ----- ^^^^^^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL - /** [Clone](std::clone::Clone) */ #[inline] +LL + /** [Clone] */ #[inline] + | + +error: redundant explicit link target + --> $DIR/redundant_explicit_links_split.rs:84:13 + | +LL | /** [Clone](std::clone::Clone) */ #[inline] pub fn split_blockcomment_singleline_attr_b() { } + | ----- ^^^^^^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL - /** [Clone](std::clone::Clone) */ #[inline] pub fn split_blockcomment_singleline_attr_b() { } +LL + /** [Clone] */ #[inline] pub fn split_blockcomment_singleline_attr_b() { } + | + +error: redundant explicit link target + --> $DIR/redundant_explicit_links_split.rs:88:13 + | +LL | /// [Clone]( + | ______-----__^ + | | | + | | because label contains path that resolves to same destination +LL | | /// std::clone::Clone) + | |_____________________^ explicit target is redundant + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL - /// [Clone]( +LL - /// std::clone::Clone) +LL + /// [Clone] + | + +error: redundant explicit link target + --> $DIR/redundant_explicit_links_split.rs:95:13 + | +LL | /// [Clone](std::clone::Clone + | ______-----__^ + | | | + | | because label contains path that resolves to same destination +LL | | /// ) + | |____^ explicit target is redundant + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL - /// [Clone](std::clone::Clone +LL - /// ) +LL + /// [Clone] + | + +error: aborting due to 16 previous errors +