From c7369891ba3265e47346bf44d6f5b5bf4451f3ca Mon Sep 17 00:00:00 2001 From: Kyle Lin Date: Fri, 30 Jun 2023 18:10:01 +0800 Subject: [PATCH] Refactor lint from rustc to rustdoc --- .../passes/collect_intra_doc_links.rs | 30 +- src/librustdoc/passes/lint.rs | 2 + .../passes/lint/redundant_explicit_links.rs | 188 +++++++++++ .../lints/redundant_explicit_links.fixed | 54 +++ .../lints/redundant_explicit_links.rs | 29 +- .../lints/redundant_explicit_links.stderr | 318 ++++++++++++++---- 6 files changed, 519 insertions(+), 102 deletions(-) create mode 100644 src/librustdoc/passes/lint/redundant_explicit_links.rs create mode 100644 tests/rustdoc-ui/lints/redundant_explicit_links.fixed diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index d78fec2cb0a..0432bd40c90 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -1041,7 +1041,6 @@ fn resolve_link( )?; self.check_redundant_explicit_link( - &res, path_str, ResolutionInfo { item_id, @@ -1388,7 +1387,6 @@ fn resolve_with_disambiguator( /// Check if resolution of inline link's display text and explicit link are same. fn check_redundant_explicit_link( &mut self, - explicit_res: &Res, explicit_link: &Box, display_res_info: ResolutionInfo, ori_link: &MarkdownLink, @@ -1415,38 +1413,14 @@ fn check_redundant_explicit_link( if explicit_len >= display_len && &explicit_link[(explicit_len - display_len)..] == display_text { - let Some((display_res, _)) = self.resolve_with_disambiguator_cached( + self.resolve_with_disambiguator_cached( display_res_info, diag_info.clone(), // this struct should really be Copy, but Range is not :( // For reference-style links we want to report only one error so unsuccessful // resolutions are cached, for other links we want to report an error every // time so they are not cached. matches!(ori_link.kind, LinkType::Reference), - ) else { - return; - }; - - if &display_res == explicit_res { - use crate::lint::REDUNDANT_EXPLICIT_LINKS; - - report_diagnostic( - self.cx.tcx, - REDUNDANT_EXPLICIT_LINKS, - "redundant explicit rustdoc link", - &diag_info, - |diag, sp, _link_range| { - if let Some(sp) = sp { - diag.note("Explicit link does not affect the original link") - .span_suggestion_hidden( - sp, - "Remove explicit link instead", - format!(""), - Applicability::MachineApplicable, - ); - } - }, - ); - } + ); } } } diff --git a/src/librustdoc/passes/lint.rs b/src/librustdoc/passes/lint.rs index e653207b9b6..c6d5b7bd346 100644 --- a/src/librustdoc/passes/lint.rs +++ b/src/librustdoc/passes/lint.rs @@ -4,6 +4,7 @@ mod bare_urls; mod check_code_block_syntax; mod html_tags; +mod redundant_explicit_links; mod unescaped_backticks; use super::Pass; @@ -29,6 +30,7 @@ fn visit_item(&mut self, item: &Item) { check_code_block_syntax::visit_item(self.cx, item); html_tags::visit_item(self.cx, item); unescaped_backticks::visit_item(self.cx, item); + redundant_explicit_links::visit_item(self.cx, item); self.visit_item_recur(item) } diff --git a/src/librustdoc/passes/lint/redundant_explicit_links.rs b/src/librustdoc/passes/lint/redundant_explicit_links.rs new file mode 100644 index 00000000000..1bccedde92a --- /dev/null +++ b/src/librustdoc/passes/lint/redundant_explicit_links.rs @@ -0,0 +1,188 @@ +use std::ops::Range; + +use pulldown_cmark::{Parser, BrokenLink, Event, Tag, LinkType, OffsetIter}; +use rustc_ast::NodeId; +use rustc_errors::SuggestionStyle; +use rustc_hir::HirId; +use rustc_hir::def::{Namespace, DefKind, DocLinkResMap, Res}; +use rustc_lint_defs::Applicability; +use rustc_span::Symbol; + +use crate::clean::Item; +use crate::clean::utils::find_nearest_parent_module; +use crate::core::DocContext; +use crate::html::markdown::main_body_opts; +use crate::passes::source_span_for_markdown_range; + +struct LinkData { + resolvable_link: Option, + resolvable_link_range: Option>, + display_link: String, +} + +pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) { + let Some(hir_id) = DocContext::as_local_hir_id(cx.tcx, item.item_id) else { + // If non-local, no need to check anything. + return; + }; + + let doc = item.doc_value(); + if doc.is_empty() { + return; + } + + check_redundant_explicit_link(cx, item, hir_id, &doc); +} + +fn check_redundant_explicit_link<'md>(cx: &DocContext<'_>, item: &Item, hir_id: HirId, doc: &'md str) { + let mut broken_line_callback = |link: BrokenLink<'md>| Some((link.reference, "".into())); + let mut offset_iter = Parser::new_with_broken_link_callback(&doc, main_body_opts(), Some(&mut broken_line_callback)).into_offset_iter(); + + while let Some((event, link_range)) = offset_iter.next() { + match event { + Event::Start(Tag::Link(link_type, dest, _)) => { + let link_data = collect_link_data(&mut offset_iter); + let dest = dest.to_string(); + + if link_type == LinkType::Inline { + check_inline_link_redundancy(cx, item, hir_id, doc, link_range, dest, link_data); + } + } + _ => {} + } + } +} + +fn check_inline_link_redundancy(cx: &DocContext<'_>, item: &Item, hir_id: HirId, doc: &str, link_range: Range, dest: String, link_data: LinkData) -> Option<()> { + let item_id = item.def_id()?; + let module_id = match cx.tcx.def_kind(item_id) { + DefKind::Mod if item.inner_docs(cx.tcx) => item_id, + _ => find_nearest_parent_module(cx.tcx, item_id).unwrap(), + }; + let resolutions = cx.tcx.doc_link_resolutions(module_id); + + 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)?); + + if dest_res == display_res { + let link_span = source_span_for_markdown_range( + cx.tcx, + &doc, + &link_range, + &item.attrs, + ).unwrap_or(item.attr_span(cx.tcx)); + let explicit_span = source_span_for_markdown_range( + cx.tcx, + &doc, + &offset_explicit_range(doc, &link_range, b'(', b')'), + &item.attrs + )?; + let display_span = source_span_for_markdown_range( + cx.tcx, + &doc, + &resolvable_link_range, + &item.attrs + )?; + + + cx.tcx.struct_span_lint_hir(crate::lint::REDUNDANT_EXPLICIT_LINKS, hir_id, explicit_span, "redundant explicit link target", |lint| { + lint.span_label(explicit_span, "explicit target is redundant") + .span_label(display_span, "because label contains path that resolves to same destination") + .note("when a link's destination is not specified,\nthe label is used to resolve intra-doc links") + .span_suggestion_with_style(link_span, "remove explicit link target", format!("[{}]", link_data.display_link), Applicability::MaybeIncorrect, SuggestionStyle::ShowAlways); + + lint + }); + } + + None +} + +fn find_resolution<'tcx>(resolutions: &'tcx DocLinkResMap, path: &str) -> Option<&'tcx Res> { + for ns in [Namespace::TypeNS, Namespace::ValueNS, Namespace::MacroNS] { + let Some(Some(res)) = resolutions.get(&(Symbol::intern(path), ns)) + else { + continue; + }; + + return Some(res); + } + + None +} + +/// Collects all neccessary data of link. +fn collect_link_data(offset_iter: &mut OffsetIter<'_, '_>) -> LinkData { + let mut resolvable_link = None; + let mut resolvable_link_range = None; + let mut display_link = String::new(); + + while let Some((event, range)) = offset_iter.next() { + match event { + Event::Text(code) => { + let code = code.to_string(); + display_link.push_str(&code); + resolvable_link = Some(code); + resolvable_link_range = Some(range); + } + Event::Code(code) => { + let code = code.to_string(); + display_link.push('`'); + display_link.push_str(&code); + display_link.push('`'); + resolvable_link = Some(code); + resolvable_link_range = Some(range); + } + Event::End(_) => { + break; + } + _ => {} + } + } + + LinkData { + resolvable_link, + resolvable_link_range, + display_link, + } +} + +fn offset_explicit_range(md: &str, link_range: &Range, open: u8, close: u8) -> Range { + let mut open_brace = !0; + let mut close_brace = !0; + for (i, b) in md.as_bytes()[link_range.clone()].iter().copied().enumerate().rev() { + let i = i + link_range.start; + if b == close { + close_brace = i; + break; + } + } + + if close_brace < link_range.start || close_brace >= link_range.end { + return link_range.clone(); + } + + let mut nesting = 1; + + for (i, b) in md.as_bytes()[link_range.start..close_brace].iter().copied().enumerate().rev() { + let i = i + link_range.start; + if b == close { + nesting += 1; + } + if b == open { + nesting -= 1; + } + if nesting == 0 { + open_brace = i; + break; + } + } + + assert!(open_brace != close_brace); + + if open_brace < link_range.start || open_brace >= link_range.end { + return link_range.clone(); + } + // do not actually include braces in the span + (open_brace + 1)..close_brace +} diff --git a/tests/rustdoc-ui/lints/redundant_explicit_links.fixed b/tests/rustdoc-ui/lints/redundant_explicit_links.fixed new file mode 100644 index 00000000000..6759ee10049 --- /dev/null +++ b/tests/rustdoc-ui/lints/redundant_explicit_links.fixed @@ -0,0 +1,54 @@ +// run-rustfix + +#![deny(rustdoc::redundant_explicit_links)] + +pub fn dummy_target() {} + +/// [dummy_target] +//~^ ERROR redundant explicit link target +/// [`dummy_target`] +//~^ ERROR redundant explicit link target +/// +/// [Vec] +//~^ ERROR redundant explicit link target +/// [`Vec`] +//~^ ERROR redundant explicit link target +/// [Vec] +//~^ ERROR redundant explicit link target +/// [`Vec`] +//~^ ERROR redundant explicit link target +/// [std::vec::Vec] +//~^ ERROR redundant explicit link target +/// [`std::vec::Vec`] +//~^ ERROR redundant explicit link target +/// [std::vec::Vec] +//~^ ERROR redundant explicit link target +/// [`std::vec::Vec`] +//~^ ERROR redundant explicit link target +/// +/// [usize] +//~^ ERROR redundant explicit link target +/// [`usize`] +//~^ ERROR redundant explicit link target +/// [usize] +//~^ ERROR redundant explicit link target +/// [`usize`] +//~^ ERROR redundant explicit link target +/// [std::primitive::usize] +//~^ ERROR redundant explicit link target +/// [`std::primitive::usize`] +//~^ ERROR redundant explicit link target +/// [std::primitive::usize] +//~^ ERROR redundant explicit link target +/// [`std::primitive::usize`] +//~^ ERROR redundant explicit link target +/// +/// [dummy_target] TEXT +//~^ ERROR redundant explicit link target +/// [`dummy_target`] TEXT +//~^ ERROR redundant explicit link target +pub fn should_warn_inline() {} + +/// [`Vec`](Vec) +/// [`Vec`](std::vec::Vec) +pub fn should_not_warn_inline() {} diff --git a/tests/rustdoc-ui/lints/redundant_explicit_links.rs b/tests/rustdoc-ui/lints/redundant_explicit_links.rs index b3203a2690f..7c30b15d993 100644 --- a/tests/rustdoc-ui/lints/redundant_explicit_links.rs +++ b/tests/rustdoc-ui/lints/redundant_explicit_links.rs @@ -1,29 +1,54 @@ +// run-rustfix + #![deny(rustdoc::redundant_explicit_links)] pub fn dummy_target() {} /// [dummy_target](dummy_target) +//~^ ERROR redundant explicit link target /// [`dummy_target`](dummy_target) +//~^ ERROR redundant explicit link target /// /// [Vec](Vec) +//~^ ERROR redundant explicit link target /// [`Vec`](Vec) +//~^ ERROR redundant explicit link target /// [Vec](std::vec::Vec) +//~^ ERROR redundant explicit link target /// [`Vec`](std::vec::Vec) +//~^ ERROR redundant explicit link target /// [std::vec::Vec](Vec) +//~^ ERROR redundant explicit link target /// [`std::vec::Vec`](Vec) +//~^ ERROR redundant explicit link target /// [std::vec::Vec](std::vec::Vec) +//~^ ERROR redundant explicit link target /// [`std::vec::Vec`](std::vec::Vec) +//~^ ERROR redundant explicit link target /// /// [usize](usize) +//~^ ERROR redundant explicit link target /// [`usize`](usize) +//~^ ERROR redundant explicit link target /// [usize](std::primitive::usize) +//~^ ERROR redundant explicit link target /// [`usize`](std::primitive::usize) +//~^ ERROR redundant explicit link target /// [std::primitive::usize](usize) +//~^ ERROR redundant explicit link target /// [`std::primitive::usize`](usize) +//~^ ERROR redundant explicit link target /// [std::primitive::usize](std::primitive::usize) +//~^ ERROR redundant explicit link target /// [`std::primitive::usize`](std::primitive::usize) -pub fn should_warn() {} +//~^ ERROR redundant explicit link target +/// +/// [dummy_target](dummy_target) TEXT +//~^ ERROR redundant explicit link target +/// [`dummy_target`](dummy_target) TEXT +//~^ ERROR redundant explicit link target +pub fn should_warn_inline() {} /// [`Vec`](Vec) /// [`Vec`](std::vec::Vec) -pub fn should_not_warn() {} +pub fn should_not_warn_inline() {} diff --git a/tests/rustdoc-ui/lints/redundant_explicit_links.stderr b/tests/rustdoc-ui/lints/redundant_explicit_links.stderr index e72105f394f..3f10a2e662d 100644 --- a/tests/rustdoc-ui/lints/redundant_explicit_links.stderr +++ b/tests/rustdoc-ui/lints/redundant_explicit_links.stderr @@ -1,133 +1,307 @@ -error: redundant explicit rustdoc link - --> $DIR/redundant_explicit_links.rs:5:20 +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:7:20 | LL | /// [dummy_target](dummy_target) - | ^^^^^^^^^^^^ + | ------------ ^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination | - = note: Explicit link does not affect the original link + = 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.rs:1:9 + --> $DIR/redundant_explicit_links.rs:3:9 | LL | #![deny(rustdoc::redundant_explicit_links)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = help: Remove explicit link instead +help: remove explicit link target + | +LL | /// [dummy_target] + | ~~~~~~~~~~~~~~ -error: redundant explicit rustdoc link - --> $DIR/redundant_explicit_links.rs:6:22 +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:9:22 | LL | /// [`dummy_target`](dummy_target) - | ^^^^^^^^^^^^ + | -------------- ^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination | - = note: Explicit link does not affect the original link - = help: Remove explicit link instead + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [`dummy_target`] + | ~~~~~~~~~~~~~~~~ -error: redundant explicit rustdoc link - --> $DIR/redundant_explicit_links.rs:8:11 +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:12:11 | LL | /// [Vec](Vec) - | ^^^ + | --- ^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination | - = note: Explicit link does not affect the original link - = help: Remove explicit link instead + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [Vec] + | ~~~~~ -error: redundant explicit rustdoc link - --> $DIR/redundant_explicit_links.rs:9:13 +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:14:13 | LL | /// [`Vec`](Vec) - | ^^^ + | ----- ^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination | - = note: Explicit link does not affect the original link - = help: Remove explicit link instead + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [`Vec`] + | ~~~~~~~ -error: redundant explicit rustdoc link - --> $DIR/redundant_explicit_links.rs:10:11 +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:16:11 | LL | /// [Vec](std::vec::Vec) - | ^^^^^^^^^^^^^ + | --- ^^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination | - = note: Explicit link does not affect the original link - = help: Remove explicit link instead + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [Vec] + | ~~~~~ -error: redundant explicit rustdoc link - --> $DIR/redundant_explicit_links.rs:11:13 +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:18:13 | LL | /// [`Vec`](std::vec::Vec) - | ^^^^^^^^^^^^^ + | ----- ^^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination | - = note: Explicit link does not affect the original link - = help: Remove explicit link instead + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [`Vec`] + | ~~~~~~~ -error: redundant explicit rustdoc link - --> $DIR/redundant_explicit_links.rs:14:21 +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:20:21 + | +LL | /// [std::vec::Vec](Vec) + | ------------- ^^^ 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 | /// [std::vec::Vec] + | ~~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:22:23 + | +LL | /// [`std::vec::Vec`](Vec) + | --------------- ^^^ 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 | /// [`std::vec::Vec`] + | ~~~~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:24:21 | LL | /// [std::vec::Vec](std::vec::Vec) - | ^^^^^^^^^^^^^ + | ------------- ^^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination | - = note: Explicit link does not affect the original link - = help: Remove explicit link instead + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [std::vec::Vec] + | ~~~~~~~~~~~~~~~ -error: redundant explicit rustdoc link - --> $DIR/redundant_explicit_links.rs:15:23 +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:26:23 | LL | /// [`std::vec::Vec`](std::vec::Vec) - | ^^^^^^^^^^^^^ + | --------------- ^^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination | - = note: Explicit link does not affect the original link - = help: Remove explicit link instead + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [`std::vec::Vec`] + | ~~~~~~~~~~~~~~~~~ -error: redundant explicit rustdoc link - --> $DIR/redundant_explicit_links.rs:17:13 +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:29:13 | LL | /// [usize](usize) - | ^^^^^ + | ----- ^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination | - = note: Explicit link does not affect the original link - = help: Remove explicit link instead + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [usize] + | ~~~~~~~ -error: redundant explicit rustdoc link - --> $DIR/redundant_explicit_links.rs:18:15 +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:31:15 | LL | /// [`usize`](usize) - | ^^^^^ + | ------- ^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination | - = note: Explicit link does not affect the original link - = help: Remove explicit link instead + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [`usize`] + | ~~~~~~~~~ -error: redundant explicit rustdoc link - --> $DIR/redundant_explicit_links.rs:19:13 +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:33:13 | LL | /// [usize](std::primitive::usize) - | ^^^^^^^^^^^^^^^^^^^^^ + | ----- ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination | - = note: Explicit link does not affect the original link - = help: Remove explicit link instead + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [usize] + | ~~~~~~~ -error: redundant explicit rustdoc link - --> $DIR/redundant_explicit_links.rs:20:15 +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:35:15 | LL | /// [`usize`](std::primitive::usize) - | ^^^^^^^^^^^^^^^^^^^^^ + | ------- ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination | - = note: Explicit link does not affect the original link - = help: Remove explicit link instead + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [`usize`] + | ~~~~~~~~~ -error: redundant explicit rustdoc link - --> $DIR/redundant_explicit_links.rs:23:29 +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:37:29 + | +LL | /// [std::primitive::usize](usize) + | --------------------- ^^^^^ 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 | /// [std::primitive::usize] + | ~~~~~~~~~~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:39:31 + | +LL | /// [`std::primitive::usize`](usize) + | ----------------------- ^^^^^ 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 | /// [`std::primitive::usize`] + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:41:29 | LL | /// [std::primitive::usize](std::primitive::usize) - | ^^^^^^^^^^^^^^^^^^^^^ + | --------------------- ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination | - = note: Explicit link does not affect the original link - = help: Remove explicit link instead + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [std::primitive::usize] + | ~~~~~~~~~~~~~~~~~~~~~~~ -error: redundant explicit rustdoc link - --> $DIR/redundant_explicit_links.rs:24:31 +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:43:31 | LL | /// [`std::primitive::usize`](std::primitive::usize) - | ^^^^^^^^^^^^^^^^^^^^^ + | ----------------------- ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination | - = note: Explicit link does not affect the original link - = help: Remove explicit link instead + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [`std::primitive::usize`] + | ~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to 14 previous errors +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:46:20 + | +LL | /// [dummy_target](dummy_target) TEXT + | ------------ ^^^^^^^^^^^^ 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 | /// [dummy_target] TEXT + | ~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:48:22 + | +LL | /// [`dummy_target`](dummy_target) TEXT + | -------------- ^^^^^^^^^^^^ 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 | /// [`dummy_target`] TEXT + | ~~~~~~~~~~~~~~~~ + +error: aborting due to 20 previous errors