Auto merge of #113167 - ChAoSUnItY:redundant_explicit_link, r=GuillaumeGomez
rustdoc: Add lint `redundant_explicit_links` Closes #87799. - Lint warns by default - Reworks link parser to cache original link's display text r? `@jyn514`
This commit is contained in:
commit
9c699a40cc
24 changed files with 2066 additions and 118 deletions
|
@ -30,7 +30,7 @@ pub use super::{
|
||||||
/// will be retrieved.
|
/// will be retrieved.
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub enum ConsumerOptions {
|
pub enum ConsumerOptions {
|
||||||
/// Retrieve the [`Body`] along with the [`BorrowSet`](super::borrow_set::BorrowSet)
|
/// Retrieve the [`Body`] along with the [`BorrowSet`]
|
||||||
/// and [`RegionInferenceContext`]. If you would like the body only, use
|
/// and [`RegionInferenceContext`]. If you would like the body only, use
|
||||||
/// [`TyCtxt::mir_promoted`].
|
/// [`TyCtxt::mir_promoted`].
|
||||||
///
|
///
|
||||||
|
|
|
@ -452,11 +452,11 @@ struct HandlerInner {
|
||||||
/// have been converted.
|
/// have been converted.
|
||||||
check_unstable_expect_diagnostics: bool,
|
check_unstable_expect_diagnostics: bool,
|
||||||
|
|
||||||
/// Expected [`Diagnostic`][diagnostic::Diagnostic]s store a [`LintExpectationId`] as part of
|
/// Expected [`Diagnostic`][struct@diagnostic::Diagnostic]s store a [`LintExpectationId`] as part of
|
||||||
/// the lint level. [`LintExpectationId`]s created early during the compilation
|
/// the lint level. [`LintExpectationId`]s created early during the compilation
|
||||||
/// (before `HirId`s have been defined) are not stable and can therefore not be
|
/// (before `HirId`s have been defined) are not stable and can therefore not be
|
||||||
/// stored on disk. This buffer stores these diagnostics until the ID has been
|
/// stored on disk. This buffer stores these diagnostics until the ID has been
|
||||||
/// replaced by a stable [`LintExpectationId`]. The [`Diagnostic`][diagnostic::Diagnostic]s are the
|
/// replaced by a stable [`LintExpectationId`]. The [`Diagnostic`][struct@diagnostic::Diagnostic]s are the
|
||||||
/// submitted for storage and added to the list of fulfilled expectations.
|
/// submitted for storage and added to the list of fulfilled expectations.
|
||||||
unstable_expect_diagnostics: Vec<Diagnostic>,
|
unstable_expect_diagnostics: Vec<Diagnostic>,
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use pulldown_cmark::{BrokenLink, Event, LinkType, Options, Parser, Tag};
|
use pulldown_cmark::{BrokenLink, CowStr, Event, LinkType, Options, Parser, Tag};
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_ast::util::comments::beautify_doc_string;
|
use rustc_ast::util::comments::beautify_doc_string;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
|
@ -392,16 +392,73 @@ pub(crate) fn attrs_to_preprocessed_links(attrs: &[ast::Attribute]) -> Vec<Box<s
|
||||||
let (doc_fragments, _) = attrs_to_doc_fragments(attrs.iter().map(|attr| (attr, None)), true);
|
let (doc_fragments, _) = attrs_to_doc_fragments(attrs.iter().map(|attr| (attr, None)), true);
|
||||||
let doc = prepare_to_doc_link_resolution(&doc_fragments).into_values().next().unwrap();
|
let doc = prepare_to_doc_link_resolution(&doc_fragments).into_values().next().unwrap();
|
||||||
|
|
||||||
Parser::new_with_broken_link_callback(
|
parse_links(&doc)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Similiar version of `markdown_links` from rustdoc.
|
||||||
|
/// This will collect destination links and display text if exists.
|
||||||
|
fn parse_links<'md>(doc: &'md str) -> Vec<Box<str>> {
|
||||||
|
let mut broken_link_callback = |link: BrokenLink<'md>| Some((link.reference, "".into()));
|
||||||
|
let mut event_iter = Parser::new_with_broken_link_callback(
|
||||||
&doc,
|
&doc,
|
||||||
main_body_opts(),
|
main_body_opts(),
|
||||||
Some(&mut |link: BrokenLink<'_>| Some((link.reference, "".into()))),
|
Some(&mut broken_link_callback),
|
||||||
)
|
)
|
||||||
.filter_map(|event| match event {
|
.into_iter();
|
||||||
Event::Start(Tag::Link(link_type, dest, _)) if may_be_doc_link(link_type) => {
|
let mut links = Vec::new();
|
||||||
Some(preprocess_link(&dest))
|
|
||||||
|
while let Some(event) = event_iter.next() {
|
||||||
|
match event {
|
||||||
|
Event::Start(Tag::Link(link_type, dest, _)) if may_be_doc_link(link_type) => {
|
||||||
|
if matches!(
|
||||||
|
link_type,
|
||||||
|
LinkType::Inline
|
||||||
|
| LinkType::ReferenceUnknown
|
||||||
|
| LinkType::Reference
|
||||||
|
| LinkType::Shortcut
|
||||||
|
| LinkType::ShortcutUnknown
|
||||||
|
) {
|
||||||
|
if let Some(display_text) = collect_link_data(&mut event_iter) {
|
||||||
|
links.push(display_text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
links.push(preprocess_link(&dest));
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
_ => None,
|
}
|
||||||
})
|
|
||||||
.collect()
|
links
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Collects additional data of link.
|
||||||
|
fn collect_link_data<'input, 'callback>(
|
||||||
|
event_iter: &mut Parser<'input, 'callback>,
|
||||||
|
) -> Option<Box<str>> {
|
||||||
|
let mut display_text: Option<String> = None;
|
||||||
|
let mut append_text = |text: CowStr<'_>| {
|
||||||
|
if let Some(display_text) = &mut display_text {
|
||||||
|
display_text.push_str(&text);
|
||||||
|
} else {
|
||||||
|
display_text = Some(text.to_string());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
while let Some(event) = event_iter.next() {
|
||||||
|
match event {
|
||||||
|
Event::Text(text) => {
|
||||||
|
append_text(text);
|
||||||
|
}
|
||||||
|
Event::Code(code) => {
|
||||||
|
append_text(code);
|
||||||
|
}
|
||||||
|
Event::End(_) => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
display_text.map(String::into_boxed_str)
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,6 +89,7 @@
|
||||||
#![allow(explicit_outlives_requirements)]
|
#![allow(explicit_outlives_requirements)]
|
||||||
#![warn(multiple_supertrait_upcastable)]
|
#![warn(multiple_supertrait_upcastable)]
|
||||||
#![cfg_attr(not(bootstrap), allow(internal_features))]
|
#![cfg_attr(not(bootstrap), allow(internal_features))]
|
||||||
|
#![cfg_attr(not(bootstrap), allow(rustdoc::redundant_explicit_links))]
|
||||||
//
|
//
|
||||||
// Library features:
|
// Library features:
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
|
|
|
@ -153,7 +153,7 @@ macro_rules! acquire {
|
||||||
///
|
///
|
||||||
/// ## `Deref` behavior
|
/// ## `Deref` behavior
|
||||||
///
|
///
|
||||||
/// `Arc<T>` automatically dereferences to `T` (via the [`Deref`][deref] trait),
|
/// `Arc<T>` automatically dereferences to `T` (via the [`Deref`] trait),
|
||||||
/// so you can call `T`'s methods on a value of type `Arc<T>`. To avoid name
|
/// so you can call `T`'s methods on a value of type `Arc<T>`. To avoid name
|
||||||
/// clashes with `T`'s methods, the methods of `Arc<T>` itself are associated
|
/// clashes with `T`'s methods, the methods of `Arc<T>` itself are associated
|
||||||
/// functions, called using [fully qualified syntax]:
|
/// functions, called using [fully qualified syntax]:
|
||||||
|
@ -187,7 +187,6 @@ macro_rules! acquire {
|
||||||
/// [mutex]: ../../std/sync/struct.Mutex.html
|
/// [mutex]: ../../std/sync/struct.Mutex.html
|
||||||
/// [rwlock]: ../../std/sync/struct.RwLock.html
|
/// [rwlock]: ../../std/sync/struct.RwLock.html
|
||||||
/// [atomic]: core::sync::atomic
|
/// [atomic]: core::sync::atomic
|
||||||
/// [deref]: core::ops::Deref
|
|
||||||
/// [downgrade]: Arc::downgrade
|
/// [downgrade]: Arc::downgrade
|
||||||
/// [upgrade]: Weak::upgrade
|
/// [upgrade]: Weak::upgrade
|
||||||
/// [RefCell\<T>]: core::cell::RefCell
|
/// [RefCell\<T>]: core::cell::RefCell
|
||||||
|
@ -1495,7 +1494,7 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> {
|
||||||
/// alignment as `T`. This is trivially true if `U` is `T`.
|
/// alignment as `T`. This is trivially true if `U` is `T`.
|
||||||
/// Note that if `U` is not `T` but has the same size and alignment, this is
|
/// Note that if `U` is not `T` but has the same size and alignment, this is
|
||||||
/// basically like transmuting references of different types. See
|
/// basically like transmuting references of different types. See
|
||||||
/// [`mem::transmute`][transmute] for more information on what
|
/// [`mem::transmute`] for more information on what
|
||||||
/// restrictions apply in this case.
|
/// restrictions apply in this case.
|
||||||
///
|
///
|
||||||
/// The raw pointer must point to a block of memory allocated by `alloc`
|
/// The raw pointer must point to a block of memory allocated by `alloc`
|
||||||
|
@ -1507,7 +1506,6 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> {
|
||||||
/// even if the returned `Arc<T>` is never accessed.
|
/// even if the returned `Arc<T>` is never accessed.
|
||||||
///
|
///
|
||||||
/// [into_raw]: Arc::into_raw
|
/// [into_raw]: Arc::into_raw
|
||||||
/// [transmute]: core::mem::transmute
|
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
|
|
@ -97,6 +97,8 @@
|
||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
#![warn(multiple_supertrait_upcastable)]
|
#![warn(multiple_supertrait_upcastable)]
|
||||||
#![cfg_attr(not(bootstrap), allow(internal_features))]
|
#![cfg_attr(not(bootstrap), allow(internal_features))]
|
||||||
|
// Do not check link redundancy on bootstraping phase
|
||||||
|
#![cfg_attr(not(bootstrap), allow(rustdoc::redundant_explicit_links))]
|
||||||
//
|
//
|
||||||
// Library features:
|
// Library features:
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
|
|
|
@ -223,6 +223,7 @@
|
||||||
#![cfg_attr(not(bootstrap), allow(internal_features))]
|
#![cfg_attr(not(bootstrap), allow(internal_features))]
|
||||||
#![deny(rustc::existing_doc_keyword)]
|
#![deny(rustc::existing_doc_keyword)]
|
||||||
#![deny(fuzzy_provenance_casts)]
|
#![deny(fuzzy_provenance_casts)]
|
||||||
|
#![cfg_attr(not(bootstrap), allow(rustdoc::redundant_explicit_links))]
|
||||||
// Ensure that std can be linked against panic_abort despite compiled with `-C panic=unwind`
|
// Ensure that std can be linked against panic_abort despite compiled with `-C panic=unwind`
|
||||||
#![deny(ffi_unwind_calls)]
|
#![deny(ffi_unwind_calls)]
|
||||||
// std may use features in a platform-specific way
|
// std may use features in a platform-specific way
|
||||||
|
|
|
@ -412,3 +412,37 @@ help: if you meant to use a literal backtick, escape it
|
||||||
|
|
||||||
warning: 1 warning emitted
|
warning: 1 warning emitted
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## `redundant_explicit_links`
|
||||||
|
|
||||||
|
This lint is **warned by default**. It detects explicit links that are same
|
||||||
|
as computed automatic links.
|
||||||
|
This usually means the explicit links is removeable. For example:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
#![warn(rustdoc::redundant_explicit_links)] // note: unnecessary - warns by default.
|
||||||
|
|
||||||
|
/// add takes 2 [`usize`](usize) and performs addition
|
||||||
|
/// on them, then returns result.
|
||||||
|
pub fn add(left: usize, right: usize) -> usize {
|
||||||
|
left + right
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Which will give:
|
||||||
|
|
||||||
|
```text
|
||||||
|
error: redundant explicit rustdoc link
|
||||||
|
--> src/lib.rs:3:27
|
||||||
|
|
|
||||||
|
3 | /// add takes 2 [`usize`](usize) and performs addition
|
||||||
|
| ^^^^^
|
||||||
|
|
|
||||||
|
= note: Explicit link does not affect the original link
|
||||||
|
note: the lint level is defined here
|
||||||
|
--> src/lib.rs:1:9
|
||||||
|
|
|
||||||
|
1 | #![deny(rustdoc::redundant_explicit_links)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
= help: Remove explicit link instead
|
||||||
|
```
|
||||||
|
|
|
@ -50,7 +50,7 @@ use crate::html::render::small_url_encode;
|
||||||
use crate::html::toc::TocBuilder;
|
use crate::html::toc::TocBuilder;
|
||||||
|
|
||||||
use pulldown_cmark::{
|
use pulldown_cmark::{
|
||||||
html, BrokenLink, CodeBlockKind, CowStr, Event, LinkType, Options, Parser, Tag,
|
html, BrokenLink, CodeBlockKind, CowStr, Event, LinkType, OffsetIter, Options, Parser, Tag,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -1240,6 +1240,7 @@ pub(crate) fn plain_text_summary(md: &str, link_names: &[RenderedLink]) -> Strin
|
||||||
pub(crate) struct MarkdownLink {
|
pub(crate) struct MarkdownLink {
|
||||||
pub kind: LinkType,
|
pub kind: LinkType,
|
||||||
pub link: String,
|
pub link: String,
|
||||||
|
pub display_text: Option<String>,
|
||||||
pub range: MarkdownLinkRange,
|
pub range: MarkdownLinkRange,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1263,8 +1264,8 @@ impl MarkdownLinkRange {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn markdown_links<R>(
|
pub(crate) fn markdown_links<'md, R>(
|
||||||
md: &str,
|
md: &'md str,
|
||||||
preprocess_link: impl Fn(MarkdownLink) -> Option<R>,
|
preprocess_link: impl Fn(MarkdownLink) -> Option<R>,
|
||||||
) -> Vec<R> {
|
) -> Vec<R> {
|
||||||
if md.is_empty() {
|
if md.is_empty() {
|
||||||
|
@ -1375,32 +1376,90 @@ pub(crate) fn markdown_links<R>(
|
||||||
MarkdownLinkRange::Destination(range.clone())
|
MarkdownLinkRange::Destination(range.clone())
|
||||||
};
|
};
|
||||||
|
|
||||||
Parser::new_with_broken_link_callback(
|
let mut broken_link_callback = |link: BrokenLink<'md>| Some((link.reference, "".into()));
|
||||||
|
let mut event_iter = Parser::new_with_broken_link_callback(
|
||||||
md,
|
md,
|
||||||
main_body_opts(),
|
main_body_opts(),
|
||||||
Some(&mut |link: BrokenLink<'_>| Some((link.reference, "".into()))),
|
Some(&mut broken_link_callback),
|
||||||
)
|
)
|
||||||
.into_offset_iter()
|
.into_offset_iter();
|
||||||
.filter_map(|(event, span)| match event {
|
let mut links = Vec::new();
|
||||||
Event::Start(Tag::Link(link_type, dest, _)) if may_be_doc_link(link_type) => {
|
|
||||||
let range = match link_type {
|
while let Some((event, span)) = event_iter.next() {
|
||||||
// Link is pulled from the link itself.
|
match event {
|
||||||
LinkType::ReferenceUnknown | LinkType::ShortcutUnknown => {
|
Event::Start(Tag::Link(link_type, dest, _)) if may_be_doc_link(link_type) => {
|
||||||
span_for_offset_backward(span, b'[', b']')
|
let range = match link_type {
|
||||||
|
// Link is pulled from the link itself.
|
||||||
|
LinkType::ReferenceUnknown | LinkType::ShortcutUnknown => {
|
||||||
|
span_for_offset_backward(span, b'[', b']')
|
||||||
|
}
|
||||||
|
LinkType::CollapsedUnknown => span_for_offset_forward(span, b'[', b']'),
|
||||||
|
LinkType::Inline => span_for_offset_backward(span, b'(', b')'),
|
||||||
|
// Link is pulled from elsewhere in the document.
|
||||||
|
LinkType::Reference | LinkType::Collapsed | LinkType::Shortcut => {
|
||||||
|
span_for_link(&dest, span)
|
||||||
|
}
|
||||||
|
LinkType::Autolink | LinkType::Email => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let display_text = if matches!(
|
||||||
|
link_type,
|
||||||
|
LinkType::Inline
|
||||||
|
| LinkType::ReferenceUnknown
|
||||||
|
| LinkType::Reference
|
||||||
|
| LinkType::Shortcut
|
||||||
|
| LinkType::ShortcutUnknown
|
||||||
|
) {
|
||||||
|
collect_link_data(&mut event_iter)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(link) = preprocess_link(MarkdownLink {
|
||||||
|
kind: link_type,
|
||||||
|
link: dest.into_string(),
|
||||||
|
display_text,
|
||||||
|
range,
|
||||||
|
}) {
|
||||||
|
links.push(link);
|
||||||
}
|
}
|
||||||
LinkType::CollapsedUnknown => span_for_offset_forward(span, b'[', b']'),
|
}
|
||||||
LinkType::Inline => span_for_offset_backward(span, b'(', b')'),
|
_ => {}
|
||||||
// Link is pulled from elsewhere in the document.
|
|
||||||
LinkType::Reference | LinkType::Collapsed | LinkType::Shortcut => {
|
|
||||||
span_for_link(&dest, span)
|
|
||||||
}
|
|
||||||
LinkType::Autolink | LinkType::Email => unreachable!(),
|
|
||||||
};
|
|
||||||
preprocess_link(MarkdownLink { kind: link_type, range, link: dest.into_string() })
|
|
||||||
}
|
}
|
||||||
_ => None,
|
}
|
||||||
})
|
|
||||||
.collect()
|
links
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Collects additional data of link.
|
||||||
|
fn collect_link_data<'input, 'callback>(
|
||||||
|
event_iter: &mut OffsetIter<'input, 'callback>,
|
||||||
|
) -> Option<String> {
|
||||||
|
let mut display_text: Option<String> = None;
|
||||||
|
let mut append_text = |text: CowStr<'_>| {
|
||||||
|
if let Some(display_text) = &mut display_text {
|
||||||
|
display_text.push_str(&text);
|
||||||
|
} else {
|
||||||
|
display_text = Some(text.to_string());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
while let Some((event, _span)) = event_iter.next() {
|
||||||
|
match event {
|
||||||
|
Event::Text(text) => {
|
||||||
|
append_text(text);
|
||||||
|
}
|
||||||
|
Event::Code(code) => {
|
||||||
|
append_text(code);
|
||||||
|
}
|
||||||
|
Event::End(_) => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
display_text
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
|
@ -185,6 +185,17 @@ declare_rustdoc_lint! {
|
||||||
"detects unescaped backticks in doc comments"
|
"detects unescaped backticks in doc comments"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare_rustdoc_lint! {
|
||||||
|
/// This lint is **warned by default**. It detects explicit links that are same
|
||||||
|
/// as computed automatic links. This usually means the explicit links is removeable.
|
||||||
|
/// This is a `rustdoc` only lint, see the documentation in the [rustdoc book].
|
||||||
|
///
|
||||||
|
/// [rustdoc book]: ../../../rustdoc/lints.html#redundant_explicit_links
|
||||||
|
REDUNDANT_EXPLICIT_LINKS,
|
||||||
|
Warn,
|
||||||
|
"detects redundant explicit links in doc comments"
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) static RUSTDOC_LINTS: Lazy<Vec<&'static Lint>> = Lazy::new(|| {
|
pub(crate) static RUSTDOC_LINTS: Lazy<Vec<&'static Lint>> = Lazy::new(|| {
|
||||||
vec![
|
vec![
|
||||||
BROKEN_INTRA_DOC_LINKS,
|
BROKEN_INTRA_DOC_LINKS,
|
||||||
|
@ -197,6 +208,7 @@ pub(crate) static RUSTDOC_LINTS: Lazy<Vec<&'static Lint>> = Lazy::new(|| {
|
||||||
BARE_URLS,
|
BARE_URLS,
|
||||||
MISSING_CRATE_LEVEL_DOCS,
|
MISSING_CRATE_LEVEL_DOCS,
|
||||||
UNESCAPED_BACKTICKS,
|
UNESCAPED_BACKTICKS,
|
||||||
|
REDUNDANT_EXPLICIT_LINKS,
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -994,7 +994,7 @@ impl LinkCollector<'_, '_> {
|
||||||
_ => find_nearest_parent_module(self.cx.tcx, item_id).unwrap(),
|
_ => find_nearest_parent_module(self.cx.tcx, item_id).unwrap(),
|
||||||
};
|
};
|
||||||
for md_link in preprocessed_markdown_links(&doc) {
|
for md_link in preprocessed_markdown_links(&doc) {
|
||||||
let link = self.resolve_link(item, item_id, module_id, &doc, &md_link);
|
let link = self.resolve_link(&doc, item, item_id, module_id, &md_link);
|
||||||
if let Some(link) = link {
|
if let Some(link) = link {
|
||||||
self.cx.cache.intra_doc_links.entry(item.item_id).or_default().insert(link);
|
self.cx.cache.intra_doc_links.entry(item.item_id).or_default().insert(link);
|
||||||
}
|
}
|
||||||
|
@ -1007,13 +1007,12 @@ impl LinkCollector<'_, '_> {
|
||||||
/// FIXME(jynelson): this is way too many arguments
|
/// FIXME(jynelson): this is way too many arguments
|
||||||
fn resolve_link(
|
fn resolve_link(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
dox: &String,
|
||||||
item: &Item,
|
item: &Item,
|
||||||
item_id: DefId,
|
item_id: DefId,
|
||||||
module_id: DefId,
|
module_id: DefId,
|
||||||
dox: &str,
|
PreprocessedMarkdownLink(pp_link, ori_link): &PreprocessedMarkdownLink,
|
||||||
link: &PreprocessedMarkdownLink,
|
|
||||||
) -> Option<ItemLink> {
|
) -> Option<ItemLink> {
|
||||||
let PreprocessedMarkdownLink(pp_link, ori_link) = link;
|
|
||||||
trace!("considering link '{}'", ori_link.link);
|
trace!("considering link '{}'", ori_link.link);
|
||||||
|
|
||||||
let diag_info = DiagnosticInfo {
|
let diag_info = DiagnosticInfo {
|
||||||
|
@ -1022,7 +1021,6 @@ impl LinkCollector<'_, '_> {
|
||||||
ori_link: &ori_link.link,
|
ori_link: &ori_link.link,
|
||||||
link_range: ori_link.range.clone(),
|
link_range: ori_link.range.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let PreprocessingInfo { path_str, disambiguator, extra_fragment, link_text } =
|
let PreprocessingInfo { path_str, disambiguator, extra_fragment, link_text } =
|
||||||
pp_link.as_ref().map_err(|err| err.report(self.cx, diag_info.clone())).ok()?;
|
pp_link.as_ref().map_err(|err| err.report(self.cx, diag_info.clone())).ok()?;
|
||||||
let disambiguator = *disambiguator;
|
let disambiguator = *disambiguator;
|
||||||
|
@ -1040,8 +1038,24 @@ impl LinkCollector<'_, '_> {
|
||||||
// resolutions are cached, for other links we want to report an error every
|
// resolutions are cached, for other links we want to report an error every
|
||||||
// time so they are not cached.
|
// time so they are not cached.
|
||||||
matches!(ori_link.kind, LinkType::Reference | LinkType::Shortcut),
|
matches!(ori_link.kind, LinkType::Reference | LinkType::Shortcut),
|
||||||
|
false,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
if ori_link.display_text.is_some() {
|
||||||
|
self.resolve_display_text(
|
||||||
|
path_str,
|
||||||
|
ResolutionInfo {
|
||||||
|
item_id,
|
||||||
|
module_id,
|
||||||
|
dis: disambiguator,
|
||||||
|
path_str: ori_link.display_text.clone()?.into_boxed_str(),
|
||||||
|
extra_fragment: extra_fragment.clone(),
|
||||||
|
},
|
||||||
|
&ori_link,
|
||||||
|
&diag_info,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Check for a primitive which might conflict with a module
|
// Check for a primitive which might conflict with a module
|
||||||
// Report the ambiguity and require that the user specify which one they meant.
|
// Report the ambiguity and require that the user specify which one they meant.
|
||||||
// FIXME: could there ever be a primitive not in the type namespace?
|
// FIXME: could there ever be a primitive not in the type namespace?
|
||||||
|
@ -1221,6 +1235,9 @@ impl LinkCollector<'_, '_> {
|
||||||
// If errors are cached then they are only reported on first occurrence
|
// If errors are cached then they are only reported on first occurrence
|
||||||
// which we want in some cases but not in others.
|
// which we want in some cases but not in others.
|
||||||
cache_errors: bool,
|
cache_errors: bool,
|
||||||
|
// If this call is intended to be recoverable, then pass true to silence.
|
||||||
|
// This is only recoverable when path is failed to resolved.
|
||||||
|
recoverable: bool,
|
||||||
) -> Option<(Res, Option<UrlFragment>)> {
|
) -> Option<(Res, Option<UrlFragment>)> {
|
||||||
if let Some(res) = self.visited_links.get(&key) {
|
if let Some(res) = self.visited_links.get(&key) {
|
||||||
if res.is_some() || cache_errors {
|
if res.is_some() || cache_errors {
|
||||||
|
@ -1228,7 +1245,7 @@ impl LinkCollector<'_, '_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut candidates = self.resolve_with_disambiguator(&key, diag.clone());
|
let mut candidates = self.resolve_with_disambiguator(&key, diag.clone(), recoverable);
|
||||||
|
|
||||||
// FIXME: it would be nice to check that the feature gate was enabled in the original crate, not just ignore it altogether.
|
// FIXME: it would be nice to check that the feature gate was enabled in the original crate, not just ignore it altogether.
|
||||||
// However I'm not sure how to check that across crates.
|
// However I'm not sure how to check that across crates.
|
||||||
|
@ -1279,6 +1296,9 @@ impl LinkCollector<'_, '_> {
|
||||||
&mut self,
|
&mut self,
|
||||||
key: &ResolutionInfo,
|
key: &ResolutionInfo,
|
||||||
diag: DiagnosticInfo<'_>,
|
diag: DiagnosticInfo<'_>,
|
||||||
|
// If this call is intended to be recoverable, then pass true to silence.
|
||||||
|
// This is only recoverable when path is failed to resolved.
|
||||||
|
recoverable: bool,
|
||||||
) -> Vec<(Res, Option<DefId>)> {
|
) -> Vec<(Res, Option<DefId>)> {
|
||||||
let disambiguator = key.dis;
|
let disambiguator = key.dis;
|
||||||
let path_str = &key.path_str;
|
let path_str = &key.path_str;
|
||||||
|
@ -1308,7 +1328,9 @@ impl LinkCollector<'_, '_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
resolution_failure(self, diag, path_str, disambiguator, smallvec![err]);
|
if !recoverable {
|
||||||
|
resolution_failure(self, diag, path_str, disambiguator, smallvec![err]);
|
||||||
|
}
|
||||||
return vec![];
|
return vec![];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1345,13 +1367,15 @@ impl LinkCollector<'_, '_> {
|
||||||
.fold(0, |acc, res| if let Ok(res) = res { acc + res.len() } else { acc });
|
.fold(0, |acc, res| if let Ok(res) = res { acc + res.len() } else { acc });
|
||||||
|
|
||||||
if len == 0 {
|
if len == 0 {
|
||||||
resolution_failure(
|
if !recoverable {
|
||||||
self,
|
resolution_failure(
|
||||||
diag,
|
self,
|
||||||
path_str,
|
diag,
|
||||||
disambiguator,
|
path_str,
|
||||||
candidates.into_iter().filter_map(|res| res.err()).collect(),
|
disambiguator,
|
||||||
);
|
candidates.into_iter().filter_map(|res| res.err()).collect(),
|
||||||
|
);
|
||||||
|
}
|
||||||
return vec![];
|
return vec![];
|
||||||
} else if len == 1 {
|
} else if len == 1 {
|
||||||
candidates.into_iter().filter_map(|res| res.ok()).flatten().collect::<Vec<_>>()
|
candidates.into_iter().filter_map(|res| res.ok()).flatten().collect::<Vec<_>>()
|
||||||
|
@ -1372,6 +1396,63 @@ impl LinkCollector<'_, '_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Resolve display text if the provided link has separated parts of links.
|
||||||
|
///
|
||||||
|
/// For example:
|
||||||
|
/// Inline link `[display_text](dest_link)` and reference link `[display_text][reference_link]` has
|
||||||
|
/// separated parts of links.
|
||||||
|
fn resolve_display_text(
|
||||||
|
&mut self,
|
||||||
|
explicit_link: &Box<str>,
|
||||||
|
display_res_info: ResolutionInfo,
|
||||||
|
ori_link: &MarkdownLink,
|
||||||
|
diag_info: &DiagnosticInfo<'_>,
|
||||||
|
) {
|
||||||
|
// Check if explicit resolution's path is same as resolution of original link's display text path, see
|
||||||
|
// tests/rustdoc-ui/lint/redundant_explicit_links.rs for more cases.
|
||||||
|
//
|
||||||
|
// To avoid disambiguator from panicking, we check if display text path is possible to be disambiguated
|
||||||
|
// into explicit path.
|
||||||
|
if !matches!(
|
||||||
|
ori_link.kind,
|
||||||
|
LinkType::Inline | LinkType::Reference | LinkType::ReferenceUnknown
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Algorithm to check if display text could possibly be the explicit link:
|
||||||
|
//
|
||||||
|
// Consider 2 links which are display text and explicit link, pick the shorter
|
||||||
|
// one as symbol and longer one as full qualified path, and tries to match symbol
|
||||||
|
// to the full qualified path's last symbol.
|
||||||
|
//
|
||||||
|
// Otherwise, check if 2 links are same, if so, skip the resolve process.
|
||||||
|
//
|
||||||
|
// Notice that this algorithm is passive, might possibly miss actual redudant cases.
|
||||||
|
let explicit_link = &explicit_link.to_string();
|
||||||
|
let display_text = ori_link.display_text.as_ref().unwrap();
|
||||||
|
let display_len = display_text.len();
|
||||||
|
let explicit_len = explicit_link.len();
|
||||||
|
|
||||||
|
if display_len == explicit_len {
|
||||||
|
// Whether they are same or not, skip the resolve process.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (explicit_len >= display_len
|
||||||
|
&& &explicit_link[(explicit_len - display_len)..] == display_text)
|
||||||
|
|| (display_len >= explicit_len
|
||||||
|
&& &display_text[(display_len - explicit_len)..] == explicit_link)
|
||||||
|
{
|
||||||
|
self.resolve_with_disambiguator_cached(
|
||||||
|
display_res_info,
|
||||||
|
diag_info.clone(), // this struct should really be Copy, but Range is not :(
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the section of a link between the backticks,
|
/// Get the section of a link between the backticks,
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
mod bare_urls;
|
mod bare_urls;
|
||||||
mod check_code_block_syntax;
|
mod check_code_block_syntax;
|
||||||
mod html_tags;
|
mod html_tags;
|
||||||
|
mod redundant_explicit_links;
|
||||||
mod unescaped_backticks;
|
mod unescaped_backticks;
|
||||||
|
|
||||||
use super::Pass;
|
use super::Pass;
|
||||||
|
@ -29,6 +30,7 @@ impl<'a, 'tcx> DocVisitor for Linter<'a, 'tcx> {
|
||||||
check_code_block_syntax::visit_item(self.cx, item);
|
check_code_block_syntax::visit_item(self.cx, item);
|
||||||
html_tags::visit_item(self.cx, item);
|
html_tags::visit_item(self.cx, item);
|
||||||
unescaped_backticks::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)
|
self.visit_item_recur(item)
|
||||||
}
|
}
|
||||||
|
|
352
src/librustdoc/passes/lint/redundant_explicit_links.rs
Normal file
352
src/librustdoc/passes/lint/redundant_explicit_links.rs
Normal file
|
@ -0,0 +1,352 @@
|
||||||
|
use std::ops::Range;
|
||||||
|
|
||||||
|
use pulldown_cmark::{BrokenLink, CowStr, Event, LinkType, OffsetIter, Parser, Tag};
|
||||||
|
use rustc_ast::NodeId;
|
||||||
|
use rustc_errors::SuggestionStyle;
|
||||||
|
use rustc_hir::def::{DefKind, DocLinkResMap, Namespace, Res};
|
||||||
|
use rustc_hir::HirId;
|
||||||
|
use rustc_lint_defs::Applicability;
|
||||||
|
use rustc_span::Symbol;
|
||||||
|
|
||||||
|
use crate::clean::utils::find_nearest_parent_module;
|
||||||
|
use crate::clean::utils::inherits_doc_hidden;
|
||||||
|
use crate::clean::Item;
|
||||||
|
use crate::core::DocContext;
|
||||||
|
use crate::html::markdown::main_body_opts;
|
||||||
|
use crate::passes::source_span_for_markdown_range;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct LinkData {
|
||||||
|
resolvable_link: Option<String>,
|
||||||
|
resolvable_link_range: Option<Range<usize>>,
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if item.link_names(&cx.cache).is_empty() {
|
||||||
|
// If there's no link names in this item,
|
||||||
|
// then we skip resolution querying to
|
||||||
|
// avoid from panicking.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let Some(item_id) = item.def_id() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let Some(local_item_id) = item_id.as_local() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let is_hidden = !cx.render_options.document_hidden
|
||||||
|
&& (item.is_doc_hidden() || inherits_doc_hidden(cx.tcx, local_item_id, None));
|
||||||
|
if is_hidden {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let is_private = !cx.render_options.document_private
|
||||||
|
&& !cx.cache.effective_visibilities.is_directly_public(cx.tcx, item_id);
|
||||||
|
if is_private {
|
||||||
|
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,
|
||||||
|
) -> Option<()> {
|
||||||
|
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();
|
||||||
|
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);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
if let Some(resolvable_link) = link_data.resolvable_link.as_ref() {
|
||||||
|
if &link_data.display_link.replace("`", "") != resolvable_link {
|
||||||
|
// Skips if display link does not match to actual
|
||||||
|
// resolvable link, usually happens if display link
|
||||||
|
// has several segments, e.g.
|
||||||
|
// [this is just an `Option`](Option)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let explicit_link = dest.to_string();
|
||||||
|
let display_link = link_data.resolvable_link.clone()?;
|
||||||
|
let explicit_len = explicit_link.len();
|
||||||
|
let display_len = display_link.len();
|
||||||
|
|
||||||
|
if (explicit_len >= display_len
|
||||||
|
&& &explicit_link[(explicit_len - display_len)..] == display_link)
|
||||||
|
|| (display_len >= explicit_len
|
||||||
|
&& &display_link[(display_len - explicit_len)..] == explicit_link)
|
||||||
|
{
|
||||||
|
match link_type {
|
||||||
|
LinkType::Inline | LinkType::ReferenceUnknown => {
|
||||||
|
check_inline_or_reference_unknown_redundancy(
|
||||||
|
cx,
|
||||||
|
item,
|
||||||
|
hir_id,
|
||||||
|
doc,
|
||||||
|
resolutions,
|
||||||
|
link_range,
|
||||||
|
dest.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,
|
||||||
|
link_data,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
/// FIXME(ChAoSUnItY): Too many arguments.
|
||||||
|
fn check_inline_or_reference_unknown_redundancy(
|
||||||
|
cx: &DocContext<'_>,
|
||||||
|
item: &Item,
|
||||||
|
hir_id: HirId,
|
||||||
|
doc: &str,
|
||||||
|
resolutions: &DocLinkResMap,
|
||||||
|
link_range: Range<usize>,
|
||||||
|
dest: String,
|
||||||
|
link_data: LinkData,
|
||||||
|
(open, close): (u8, u8),
|
||||||
|
) -> Option<()> {
|
||||||
|
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, open, close),
|
||||||
|
&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
|
||||||
|
}
|
||||||
|
|
||||||
|
/// FIXME(ChAoSUnItY): Too many arguments.
|
||||||
|
fn check_reference_redundancy(
|
||||||
|
cx: &DocContext<'_>,
|
||||||
|
item: &Item,
|
||||||
|
hir_id: HirId,
|
||||||
|
doc: &str,
|
||||||
|
resolutions: &DocLinkResMap,
|
||||||
|
link_range: Range<usize>,
|
||||||
|
dest: &CowStr<'_>,
|
||||||
|
link_data: LinkData,
|
||||||
|
) -> Option<()> {
|
||||||
|
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.clone(), b'[', b']'),
|
||||||
|
&item.attrs,
|
||||||
|
)?;
|
||||||
|
let display_span =
|
||||||
|
source_span_for_markdown_range(cx.tcx, &doc, &resolvable_link_range, &item.attrs)?;
|
||||||
|
let def_span = source_span_for_markdown_range(
|
||||||
|
cx.tcx,
|
||||||
|
&doc,
|
||||||
|
&offset_reference_def_range(doc, dest, 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")
|
||||||
|
.span_note(def_span, "referenced explicit link target defined here")
|
||||||
|
.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(resolutions: &DocLinkResMap, path: &str) -> Option<Res<NodeId>> {
|
||||||
|
[Namespace::TypeNS, Namespace::ValueNS, Namespace::MacroNS]
|
||||||
|
.into_iter()
|
||||||
|
.find_map(|ns| resolutions.get(&(Symbol::intern(path), ns)).copied().flatten())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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<usize>, open: u8, close: u8) -> Range<usize> {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
// do not actually include braces in the span
|
||||||
|
(open_brace + 1)..close_brace
|
||||||
|
}
|
||||||
|
|
||||||
|
fn offset_reference_def_range(
|
||||||
|
md: &str,
|
||||||
|
dest: &CowStr<'_>,
|
||||||
|
link_range: Range<usize>,
|
||||||
|
) -> Range<usize> {
|
||||||
|
// For diagnostics, we want to underline the link's definition but `span` will point at
|
||||||
|
// where the link is used. This is a problem for reference-style links, where the definition
|
||||||
|
// is separate from the usage.
|
||||||
|
|
||||||
|
match dest {
|
||||||
|
// `Borrowed` variant means the string (the link's destination) may come directly from
|
||||||
|
// the markdown text and we can locate the original link destination.
|
||||||
|
// NOTE: LinkReplacer also provides `Borrowed` but possibly from other sources,
|
||||||
|
// so `locate()` can fall back to use `span`.
|
||||||
|
CowStr::Borrowed(s) => {
|
||||||
|
// FIXME: remove this function once pulldown_cmark can provide spans for link definitions.
|
||||||
|
unsafe {
|
||||||
|
let s_start = dest.as_ptr();
|
||||||
|
let s_end = s_start.add(s.len());
|
||||||
|
let md_start = md.as_ptr();
|
||||||
|
let md_end = md_start.add(md.len());
|
||||||
|
if md_start <= s_start && s_end <= md_end {
|
||||||
|
let start = s_start.offset_from(md_start) as usize;
|
||||||
|
let end = s_end.offset_from(md_start) as usize;
|
||||||
|
start..end
|
||||||
|
} else {
|
||||||
|
link_range
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// For anything else, we can only use the provided range.
|
||||||
|
CowStr::Boxed(_) | CowStr::Inlined(_) => link_range,
|
||||||
|
}
|
||||||
|
}
|
13
tests/rustdoc-ui/lints/inline-doc-link.rs
Normal file
13
tests/rustdoc-ui/lints/inline-doc-link.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
// Regression test for <https://github.com/rust-lang/rust/pull/113167>
|
||||||
|
|
||||||
|
// check-pass
|
||||||
|
#![deny(rustdoc::redundant_explicit_links)]
|
||||||
|
|
||||||
|
mod m {
|
||||||
|
pub enum ValueEnum {}
|
||||||
|
}
|
||||||
|
mod m2 {
|
||||||
|
/// [`ValueEnum`]
|
||||||
|
pub use crate::m::ValueEnum;
|
||||||
|
}
|
||||||
|
pub use m2::ValueEnum;
|
7
tests/rustdoc-ui/lints/no-redundancy.rs
Normal file
7
tests/rustdoc-ui/lints/no-redundancy.rs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
// check-pass
|
||||||
|
|
||||||
|
#![deny(rustdoc::redundant_explicit_links)]
|
||||||
|
|
||||||
|
/// [Vec][std::vec::Vec#examples] should not warn, because it's not actually redundant!
|
||||||
|
/// [This is just an `Option`][std::option::Option] has different display content to actual link!
|
||||||
|
pub fn func() {}
|
158
tests/rustdoc-ui/lints/redundant_explicit_links.fixed
Normal file
158
tests/rustdoc-ui/lints/redundant_explicit_links.fixed
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
// 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<T>`](Vec)
|
||||||
|
/// [`Vec<T>`](std::vec::Vec)
|
||||||
|
pub fn should_not_warn_inline() {}
|
||||||
|
|
||||||
|
/// [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_reference_unknown() {}
|
||||||
|
|
||||||
|
/// [`Vec<T>`][Vec]
|
||||||
|
/// [`Vec<T>`][std::vec::Vec]
|
||||||
|
pub fn should_not_warn_reference_unknown() {}
|
||||||
|
|
||||||
|
/// [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
|
||||||
|
///
|
||||||
|
/// [dummy_target]: dummy_target
|
||||||
|
/// [Vec]: Vec
|
||||||
|
/// [std::vec::Vec]: Vec
|
||||||
|
/// [usize]: usize
|
||||||
|
/// [std::primitive::usize]: usize
|
||||||
|
pub fn should_warn_reference() {}
|
||||||
|
|
||||||
|
/// [`Vec<T>`]: Vec
|
||||||
|
/// [`Vec<T>`]: std::vec::Vec
|
||||||
|
pub fn should_not_warn_reference() {}
|
158
tests/rustdoc-ui/lints/redundant_explicit_links.rs
Normal file
158
tests/rustdoc-ui/lints/redundant_explicit_links.rs
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
// 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)
|
||||||
|
//~^ 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<T>`](Vec)
|
||||||
|
/// [`Vec<T>`](std::vec::Vec)
|
||||||
|
pub fn should_not_warn_inline() {}
|
||||||
|
|
||||||
|
/// [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]
|
||||||
|
//~^ 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_reference_unknown() {}
|
||||||
|
|
||||||
|
/// [`Vec<T>`][Vec]
|
||||||
|
/// [`Vec<T>`][std::vec::Vec]
|
||||||
|
pub fn should_not_warn_reference_unknown() {}
|
||||||
|
|
||||||
|
/// [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]
|
||||||
|
//~^ 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
|
||||||
|
///
|
||||||
|
/// [dummy_target]: dummy_target
|
||||||
|
/// [Vec]: Vec
|
||||||
|
/// [std::vec::Vec]: Vec
|
||||||
|
/// [usize]: usize
|
||||||
|
/// [std::primitive::usize]: usize
|
||||||
|
pub fn should_warn_reference() {}
|
||||||
|
|
||||||
|
/// [`Vec<T>`]: Vec
|
||||||
|
/// [`Vec<T>`]: std::vec::Vec
|
||||||
|
pub fn should_not_warn_reference() {}
|
1007
tests/rustdoc-ui/lints/redundant_explicit_links.stderr
Normal file
1007
tests/rustdoc-ui/lints/redundant_explicit_links.stderr
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,7 @@
|
||||||
#![deny(rustdoc::unescaped_backticks)]
|
#![deny(rustdoc::unescaped_backticks)]
|
||||||
#![allow(rustdoc::broken_intra_doc_links)]
|
#![allow(rustdoc::broken_intra_doc_links)]
|
||||||
#![allow(rustdoc::invalid_html_tags)]
|
#![allow(rustdoc::invalid_html_tags)]
|
||||||
|
#![allow(rustdoc::redundant_explicit_links)]
|
||||||
|
|
||||||
///
|
///
|
||||||
pub fn empty() {}
|
pub fn empty() {}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:186:70
|
--> $DIR/unescaped_backticks.rs:187:70
|
||||||
|
|
|
|
||||||
LL | /// if you want your MIR to be modified by the full MIR pipeline, or `#![custom_mir(dialect =
|
LL | /// if you want your MIR to be modified by the full MIR pipeline, or `#![custom_mir(dialect =
|
||||||
| ^
|
| ^
|
||||||
|
@ -19,7 +19,7 @@ LL | /// if you want your MIR to be modified by the full MIR pipeline, or \`#![c
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:231:13
|
--> $DIR/unescaped_backticks.rs:232:13
|
||||||
|
|
|
|
||||||
LL | //! `#![rustc_expected_cgu_reuse(module="spike", cfg="rpass2", kind="post-lto")]
|
LL | //! `#![rustc_expected_cgu_reuse(module="spike", cfg="rpass2", kind="post-lto")]
|
||||||
| ^
|
| ^
|
||||||
|
@ -34,7 +34,7 @@ LL | //! \`#![rustc_expected_cgu_reuse(module="spike", cfg="rpass2", kin
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:236:13
|
--> $DIR/unescaped_backticks.rs:237:13
|
||||||
|
|
|
|
||||||
LL | /// `cfg=...
|
LL | /// `cfg=...
|
||||||
| ^
|
| ^
|
||||||
|
@ -49,7 +49,7 @@ LL | /// \`cfg=...
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:240:42
|
--> $DIR/unescaped_backticks.rs:241:42
|
||||||
|
|
|
|
||||||
LL | /// `cfg=... and not `#[cfg_attr]`
|
LL | /// `cfg=... and not `#[cfg_attr]`
|
||||||
| ^
|
| ^
|
||||||
|
@ -64,7 +64,7 @@ LL | /// `cfg=... and not `#[cfg_attr]\`
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:192:91
|
--> $DIR/unescaped_backticks.rs:193:91
|
||||||
|
|
|
|
||||||
LL | /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg to
|
LL | /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg to
|
||||||
| ^
|
| ^
|
||||||
|
@ -79,7 +79,7 @@ LL | /// Constructs a `TyKind::Error` type and registers a `delay_span_bug`
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:201:34
|
--> $DIR/unescaped_backticks.rs:202:34
|
||||||
|
|
|
|
||||||
LL | /// in `nt_to_tokenstream`
|
LL | /// in `nt_to_tokenstream`
|
||||||
| ^
|
| ^
|
||||||
|
@ -94,7 +94,7 @@ LL | /// in `nt_to_tokenstream\`
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:207:62
|
--> $DIR/unescaped_backticks.rs:208:62
|
||||||
|
|
|
|
||||||
LL | /// that `Option<Symbol>` only takes up 4 bytes, because `newtype_index! reserves
|
LL | /// that `Option<Symbol>` only takes up 4 bytes, because `newtype_index! reserves
|
||||||
| ^
|
| ^
|
||||||
|
@ -109,7 +109,7 @@ LL | /// that `Option<Symbol>` only takes up 4 bytes, because \`newtype_inde
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:215:52
|
--> $DIR/unescaped_backticks.rs:216:52
|
||||||
|
|
|
|
||||||
LL | /// also avoids the need to import `OpenOptions`.
|
LL | /// also avoids the need to import `OpenOptions`.
|
||||||
| ^
|
| ^
|
||||||
|
@ -124,7 +124,7 @@ LL | /// also avoids the need to import `OpenOptions\`.
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:220:46
|
--> $DIR/unescaped_backticks.rs:221:46
|
||||||
|
|
|
|
||||||
LL | /// `HybridBitSet`. Has no effect if `row` does not exist.
|
LL | /// `HybridBitSet`. Has no effect if `row` does not exist.
|
||||||
| ^
|
| ^
|
||||||
|
@ -139,7 +139,7 @@ LL | /// `HybridBitSet`. Has no effect if `row\` does not exist.
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:246:12
|
--> $DIR/unescaped_backticks.rs:247:12
|
||||||
|
|
|
|
||||||
LL | /// RWU`s can get very large, so it uses a more compact representation.
|
LL | /// RWU`s can get very large, so it uses a more compact representation.
|
||||||
| ^
|
| ^
|
||||||
|
@ -154,7 +154,7 @@ LL | /// RWU\`s can get very large, so it uses a more compact representation
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:253:15
|
--> $DIR/unescaped_backticks.rs:254:15
|
||||||
|
|
|
|
||||||
LL | /// in `U2`.
|
LL | /// in `U2`.
|
||||||
| ^
|
| ^
|
||||||
|
@ -169,7 +169,7 @@ LL | /// in `U2\`.
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:270:42
|
--> $DIR/unescaped_backticks.rs:271:42
|
||||||
|
|
|
|
||||||
LL | /// because it contains `[type error]`. Yuck! (See issue #29857 for
|
LL | /// because it contains `[type error]`. Yuck! (See issue #29857 for
|
||||||
| ^
|
| ^
|
||||||
|
@ -184,7 +184,7 @@ LL | /// because it contains `[type error]\`. Yuck! (See issue #29857 for
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:280:53
|
--> $DIR/unescaped_backticks.rs:281:53
|
||||||
|
|
|
|
||||||
LL | /// well as the second instance of `A: AutoTrait`) to suppress
|
LL | /// well as the second instance of `A: AutoTrait`) to suppress
|
||||||
| ^
|
| ^
|
||||||
|
@ -199,7 +199,7 @@ LL | /// well as the second instance of `A: AutoTrait\`) to suppress
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:290:40
|
--> $DIR/unescaped_backticks.rs:291:40
|
||||||
|
|
|
|
||||||
LL | /// `'a` with `'b` and not `'static`. But it will have to do for
|
LL | /// `'a` with `'b` and not `'static`. But it will have to do for
|
||||||
| ^
|
| ^
|
||||||
|
@ -211,7 +211,7 @@ LL | /// `'a` with `'b` and not `'static\`. But it will have to do for
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:299:54
|
--> $DIR/unescaped_backticks.rs:300:54
|
||||||
|
|
|
|
||||||
LL | /// `None`. Otherwise, it will return `Some(Dispatch)`.
|
LL | /// `None`. Otherwise, it will return `Some(Dispatch)`.
|
||||||
| ^
|
| ^
|
||||||
|
@ -226,7 +226,7 @@ LL | /// `None`. Otherwise, it will return `Some(Dispatch)\`.
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:303:13
|
--> $DIR/unescaped_backticks.rs:304:13
|
||||||
|
|
|
|
||||||
LL | /// or `None` if it isn't.
|
LL | /// or `None` if it isn't.
|
||||||
| ^
|
| ^
|
||||||
|
@ -238,7 +238,7 @@ LL | /// or `None\` if it isn't.
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:307:14
|
--> $DIR/unescaped_backticks.rs:308:14
|
||||||
|
|
|
|
||||||
LL | /// `on_event` should be called.
|
LL | /// `on_event` should be called.
|
||||||
| ^
|
| ^
|
||||||
|
@ -253,7 +253,7 @@ LL | /// `on_event\` should be called.
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:312:29
|
--> $DIR/unescaped_backticks.rs:313:29
|
||||||
|
|
|
|
||||||
LL | /// [`rebuild_interest_cache`][rebuild] is called after the value of the max
|
LL | /// [`rebuild_interest_cache`][rebuild] is called after the value of the max
|
||||||
| ^
|
| ^
|
||||||
|
@ -268,7 +268,7 @@ LL | /// [`rebuild_interest_cache\`][rebuild] is called after the value of the m
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:322:5
|
--> $DIR/unescaped_backticks.rs:323:5
|
||||||
|
|
|
|
||||||
LL | / /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
|
LL | / /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
|
||||||
LL | |
|
LL | |
|
||||||
|
@ -287,7 +287,7 @@ LL | | /// level changes.
|
||||||
to this: `None`. Otherwise, it will return `Some(Dispatch)\`.
|
to this: `None`. Otherwise, it will return `Some(Dispatch)\`.
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:322:5
|
--> $DIR/unescaped_backticks.rs:323:5
|
||||||
|
|
|
|
||||||
LL | / /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
|
LL | / /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
|
||||||
LL | |
|
LL | |
|
||||||
|
@ -304,7 +304,7 @@ LL | | /// level changes.
|
||||||
to this: or `None\` if it isn't.
|
to this: or `None\` if it isn't.
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:322:5
|
--> $DIR/unescaped_backticks.rs:323:5
|
||||||
|
|
|
|
||||||
LL | / /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
|
LL | / /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
|
||||||
LL | |
|
LL | |
|
||||||
|
@ -323,7 +323,7 @@ LL | | /// level changes.
|
||||||
to this: `on_event\` should be called.
|
to this: `on_event\` should be called.
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:322:5
|
--> $DIR/unescaped_backticks.rs:323:5
|
||||||
|
|
|
|
||||||
LL | / /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
|
LL | / /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
|
||||||
LL | |
|
LL | |
|
||||||
|
@ -342,7 +342,7 @@ LL | | /// level changes.
|
||||||
to this: [`rebuild_interest_cache\`][rebuild] is called after the value of the max
|
to this: [`rebuild_interest_cache\`][rebuild] is called after the value of the max
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:348:56
|
--> $DIR/unescaped_backticks.rs:349:56
|
||||||
|
|
|
|
||||||
LL | /// instead and use [`CloneCounterObserver::counter`] to increment.
|
LL | /// instead and use [`CloneCounterObserver::counter`] to increment.
|
||||||
| ^
|
| ^
|
||||||
|
@ -354,7 +354,7 @@ LL | /// instead and use [`CloneCounterObserver::counter\`] to increment.
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:11:5
|
--> $DIR/unescaped_backticks.rs:12:5
|
||||||
|
|
|
|
||||||
LL | /// `
|
LL | /// `
|
||||||
| ^
|
| ^
|
||||||
|
@ -366,7 +366,7 @@ LL | /// \`
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:18:7
|
--> $DIR/unescaped_backticks.rs:19:7
|
||||||
|
|
|
|
||||||
LL | /// \`
|
LL | /// \`
|
||||||
| ^
|
| ^
|
||||||
|
@ -381,7 +381,7 @@ LL | /// \\`
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:25:6
|
--> $DIR/unescaped_backticks.rs:26:6
|
||||||
|
|
|
|
||||||
LL | /// [`link1]
|
LL | /// [`link1]
|
||||||
| ^
|
| ^
|
||||||
|
@ -396,7 +396,7 @@ LL | /// [\`link1]
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:29:11
|
--> $DIR/unescaped_backticks.rs:30:11
|
||||||
|
|
|
|
||||||
LL | /// [link2`]
|
LL | /// [link2`]
|
||||||
| ^
|
| ^
|
||||||
|
@ -411,7 +411,7 @@ LL | /// [link2\`]
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:33:6
|
--> $DIR/unescaped_backticks.rs:34:6
|
||||||
|
|
|
|
||||||
LL | /// [`link_long](link_long)
|
LL | /// [`link_long](link_long)
|
||||||
| ^
|
| ^
|
||||||
|
@ -426,7 +426,7 @@ LL | /// [\`link_long](link_long)
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:37:6
|
--> $DIR/unescaped_backticks.rs:38:6
|
||||||
|
|
|
|
||||||
LL | /// [`broken-link]
|
LL | /// [`broken-link]
|
||||||
| ^
|
| ^
|
||||||
|
@ -441,7 +441,7 @@ LL | /// [\`broken-link]
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:44:8
|
--> $DIR/unescaped_backticks.rs:45:8
|
||||||
|
|
|
|
||||||
LL | /// <x:`>
|
LL | /// <x:`>
|
||||||
| ^
|
| ^
|
||||||
|
@ -456,7 +456,7 @@ LL | /// <x:\`>
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:54:6
|
--> $DIR/unescaped_backticks.rs:55:6
|
||||||
|
|
|
|
||||||
LL | /// 🦀`🦀
|
LL | /// 🦀`🦀
|
||||||
| ^
|
| ^
|
||||||
|
@ -475,7 +475,7 @@ LL | /// 🦀\`🦀
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:58:5
|
--> $DIR/unescaped_backticks.rs:59:5
|
||||||
|
|
|
|
||||||
LL | /// `foo(
|
LL | /// `foo(
|
||||||
| ^
|
| ^
|
||||||
|
@ -490,7 +490,7 @@ LL | /// \`foo(
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:64:14
|
--> $DIR/unescaped_backticks.rs:65:14
|
||||||
|
|
|
|
||||||
LL | /// `foo `bar`
|
LL | /// `foo `bar`
|
||||||
| ^
|
| ^
|
||||||
|
@ -505,7 +505,7 @@ LL | /// `foo `bar\`
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:70:5
|
--> $DIR/unescaped_backticks.rs:71:5
|
||||||
|
|
|
|
||||||
LL | /// `foo(
|
LL | /// `foo(
|
||||||
| ^
|
| ^
|
||||||
|
@ -520,7 +520,7 @@ LL | /// \`foo(
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:75:83
|
--> $DIR/unescaped_backticks.rs:76:83
|
||||||
|
|
|
|
||||||
LL | /// Addition is commutative, which means that add(a, b)` is the same as `add(b, a)`.
|
LL | /// Addition is commutative, which means that add(a, b)` is the same as `add(b, a)`.
|
||||||
| ^
|
| ^
|
||||||
|
@ -535,7 +535,7 @@ LL | /// Addition is commutative, which means that add(a, b)` is the same as `ad
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:79:51
|
--> $DIR/unescaped_backticks.rs:80:51
|
||||||
|
|
|
|
||||||
LL | /// or even to add a number `n` to 42 (`add(42, b)`)!
|
LL | /// or even to add a number `n` to 42 (`add(42, b)`)!
|
||||||
| ^
|
| ^
|
||||||
|
@ -550,7 +550,7 @@ LL | /// or even to add a number `n` to 42 (`add(42, b)\`)!
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:83:83
|
--> $DIR/unescaped_backticks.rs:84:83
|
||||||
|
|
|
|
||||||
LL | /// Addition is commutative, which means that `add(a, b) is the same as `add(b, a)`.
|
LL | /// Addition is commutative, which means that `add(a, b) is the same as `add(b, a)`.
|
||||||
| ^
|
| ^
|
||||||
|
@ -565,7 +565,7 @@ LL | /// Addition is commutative, which means that `add(a, b) is the same as `ad
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:87:51
|
--> $DIR/unescaped_backticks.rs:88:51
|
||||||
|
|
|
|
||||||
LL | /// or even to add a number `n` to 42 (`add(42, n)`)!
|
LL | /// or even to add a number `n` to 42 (`add(42, n)`)!
|
||||||
| ^
|
| ^
|
||||||
|
@ -580,7 +580,7 @@ LL | /// or even to add a number `n` to 42 (`add(42, n)\`)!
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:91:83
|
--> $DIR/unescaped_backticks.rs:92:83
|
||||||
|
|
|
|
||||||
LL | /// Addition is commutative, which means that `add(a, b)` is the same as add(b, a)`.
|
LL | /// Addition is commutative, which means that `add(a, b)` is the same as add(b, a)`.
|
||||||
| ^
|
| ^
|
||||||
|
@ -595,7 +595,7 @@ LL | /// Addition is commutative, which means that `add(a, b)` is the same as ad
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:95:50
|
--> $DIR/unescaped_backticks.rs:96:50
|
||||||
|
|
|
|
||||||
LL | /// or even to add a number `n` to 42 (add(42, n)`)!
|
LL | /// or even to add a number `n` to 42 (add(42, n)`)!
|
||||||
| ^
|
| ^
|
||||||
|
@ -610,7 +610,7 @@ LL | /// or even to add a number `n` to 42 (add(42, n)\`)!
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:99:74
|
--> $DIR/unescaped_backticks.rs:100:74
|
||||||
|
|
|
|
||||||
LL | /// Addition is commutative, which means that `add(a, b)` is the same as `add(b, a).
|
LL | /// Addition is commutative, which means that `add(a, b)` is the same as `add(b, a).
|
||||||
| ^
|
| ^
|
||||||
|
@ -625,7 +625,7 @@ LL | /// Addition is commutative, which means that `add(a, b)` is the same as \`
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:103:51
|
--> $DIR/unescaped_backticks.rs:104:51
|
||||||
|
|
|
|
||||||
LL | /// or even to add a number `n` to 42 (`add(42, n)`)!
|
LL | /// or even to add a number `n` to 42 (`add(42, n)`)!
|
||||||
| ^
|
| ^
|
||||||
|
@ -640,7 +640,7 @@ LL | /// or even to add a number `n` to 42 (`add(42, n)\`)!
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:107:1
|
--> $DIR/unescaped_backticks.rs:108:1
|
||||||
|
|
|
|
||||||
LL | #[doc = "`"]
|
LL | #[doc = "`"]
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
@ -651,7 +651,7 @@ LL | #[doc = "`"]
|
||||||
to this: \`
|
to this: \`
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:114:1
|
--> $DIR/unescaped_backticks.rs:115:1
|
||||||
|
|
|
|
||||||
LL | #[doc = concat!("\\", "`")]
|
LL | #[doc = concat!("\\", "`")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -664,7 +664,7 @@ LL | #[doc = concat!("\\", "`")]
|
||||||
to this: \\`
|
to this: \\`
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:118:1
|
--> $DIR/unescaped_backticks.rs:119:1
|
||||||
|
|
|
|
||||||
LL | #[doc = "Addition is commutative, which means that add(a, b)` is the same as `add(b, a)`."]
|
LL | #[doc = "Addition is commutative, which means that add(a, b)` is the same as `add(b, a)`."]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -677,7 +677,7 @@ LL | #[doc = "Addition is commutative, which means that add(a, b)` is the same a
|
||||||
to this: Addition is commutative, which means that add(a, b)` is the same as `add(b, a)\`.
|
to this: Addition is commutative, which means that add(a, b)` is the same as `add(b, a)\`.
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:122:1
|
--> $DIR/unescaped_backticks.rs:123:1
|
||||||
|
|
|
|
||||||
LL | #[doc = "Addition is commutative, which means that `add(a, b) is the same as `add(b, a)`."]
|
LL | #[doc = "Addition is commutative, which means that `add(a, b) is the same as `add(b, a)`."]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -690,7 +690,7 @@ LL | #[doc = "Addition is commutative, which means that `add(a, b) is the same a
|
||||||
to this: Addition is commutative, which means that `add(a, b) is the same as `add(b, a)\`.
|
to this: Addition is commutative, which means that `add(a, b) is the same as `add(b, a)\`.
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:126:1
|
--> $DIR/unescaped_backticks.rs:127:1
|
||||||
|
|
|
|
||||||
LL | #[doc = "Addition is commutative, which means that `add(a, b)` is the same as add(b, a)`."]
|
LL | #[doc = "Addition is commutative, which means that `add(a, b)` is the same as add(b, a)`."]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -703,7 +703,7 @@ LL | #[doc = "Addition is commutative, which means that `add(a, b)` is the same
|
||||||
to this: Addition is commutative, which means that `add(a, b)` is the same as add(b, a)\`.
|
to this: Addition is commutative, which means that `add(a, b)` is the same as add(b, a)\`.
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:130:1
|
--> $DIR/unescaped_backticks.rs:131:1
|
||||||
|
|
|
|
||||||
LL | #[doc = "Addition is commutative, which means that `add(a, b)` is the same as `add(b, a)."]
|
LL | #[doc = "Addition is commutative, which means that `add(a, b)` is the same as `add(b, a)."]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -716,7 +716,7 @@ LL | #[doc = "Addition is commutative, which means that `add(a, b)` is the same
|
||||||
to this: Addition is commutative, which means that `add(a, b)` is the same as \`add(b, a).
|
to this: Addition is commutative, which means that `add(a, b)` is the same as \`add(b, a).
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:135:5
|
--> $DIR/unescaped_backticks.rs:136:5
|
||||||
|
|
|
|
||||||
LL | /// `foo
|
LL | /// `foo
|
||||||
| ^
|
| ^
|
||||||
|
@ -731,7 +731,7 @@ LL | /// \`foo
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:139:7
|
--> $DIR/unescaped_backticks.rs:140:7
|
||||||
|
|
|
|
||||||
LL | /// # `(heading
|
LL | /// # `(heading
|
||||||
| ^
|
| ^
|
||||||
|
@ -746,7 +746,7 @@ LL | /// # \`(heading
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:141:17
|
--> $DIR/unescaped_backticks.rs:142:17
|
||||||
|
|
|
|
||||||
LL | /// ## heading2)`
|
LL | /// ## heading2)`
|
||||||
| ^
|
| ^
|
||||||
|
@ -761,7 +761,7 @@ LL | /// ## heading2)\`
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:144:11
|
--> $DIR/unescaped_backticks.rs:145:11
|
||||||
|
|
|
|
||||||
LL | /// multi `(
|
LL | /// multi `(
|
||||||
| ^
|
| ^
|
||||||
|
@ -776,7 +776,7 @@ LL | /// multi \`(
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:150:10
|
--> $DIR/unescaped_backticks.rs:151:10
|
||||||
|
|
|
|
||||||
LL | /// para)`(graph
|
LL | /// para)`(graph
|
||||||
| ^
|
| ^
|
||||||
|
@ -795,7 +795,7 @@ LL | /// para)\`(graph
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:153:10
|
--> $DIR/unescaped_backticks.rs:154:10
|
||||||
|
|
|
|
||||||
LL | /// para)`(graph2
|
LL | /// para)`(graph2
|
||||||
| ^
|
| ^
|
||||||
|
@ -814,7 +814,7 @@ LL | /// para)\`(graph2
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:156:12
|
--> $DIR/unescaped_backticks.rs:157:12
|
||||||
|
|
|
|
||||||
LL | /// 1. foo)`
|
LL | /// 1. foo)`
|
||||||
| ^
|
| ^
|
||||||
|
@ -829,7 +829,7 @@ LL | /// 1. foo)\`
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:158:8
|
--> $DIR/unescaped_backticks.rs:159:8
|
||||||
|
|
|
|
||||||
LL | /// 2. `(bar
|
LL | /// 2. `(bar
|
||||||
| ^
|
| ^
|
||||||
|
@ -844,7 +844,7 @@ LL | /// 2. \`(bar
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:160:11
|
--> $DIR/unescaped_backticks.rs:161:11
|
||||||
|
|
|
|
||||||
LL | /// * baz)`
|
LL | /// * baz)`
|
||||||
| ^
|
| ^
|
||||||
|
@ -859,7 +859,7 @@ LL | /// * baz)\`
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:162:7
|
--> $DIR/unescaped_backticks.rs:163:7
|
||||||
|
|
|
|
||||||
LL | /// * `(quux
|
LL | /// * `(quux
|
||||||
| ^
|
| ^
|
||||||
|
@ -874,7 +874,7 @@ LL | /// * \`(quux
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:165:5
|
--> $DIR/unescaped_backticks.rs:166:5
|
||||||
|
|
|
|
||||||
LL | /// `#![this_is_actually_an_image(and(not), an = "attribute")]
|
LL | /// `#![this_is_actually_an_image(and(not), an = "attribute")]
|
||||||
| ^
|
| ^
|
||||||
|
@ -889,7 +889,7 @@ LL | /// \`#![this_is_actually_an_image(and(not), an = "attribute")]
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:168:62
|
--> $DIR/unescaped_backticks.rs:169:62
|
||||||
|
|
|
|
||||||
LL | /// #![this_is_actually_an_image(and(not), an = "attribute")]`
|
LL | /// #![this_is_actually_an_image(and(not), an = "attribute")]`
|
||||||
| ^
|
| ^
|
||||||
|
@ -904,7 +904,7 @@ LL | /// #![this_is_actually_an_image(and(not), an = "attribute")]\`
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:173:7
|
--> $DIR/unescaped_backticks.rs:174:7
|
||||||
|
|
|
|
||||||
LL | /// | `table( | )head` |
|
LL | /// | `table( | )head` |
|
||||||
| ^
|
| ^
|
||||||
|
@ -919,7 +919,7 @@ LL | /// | \`table( | )head` |
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:173:22
|
--> $DIR/unescaped_backticks.rs:174:22
|
||||||
|
|
|
|
||||||
LL | /// | `table( | )head` |
|
LL | /// | `table( | )head` |
|
||||||
| ^
|
| ^
|
||||||
|
@ -934,7 +934,7 @@ LL | /// | `table( | )head\` |
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:177:12
|
--> $DIR/unescaped_backticks.rs:178:12
|
||||||
|
|
|
|
||||||
LL | /// | table`( | )`body |
|
LL | /// | table`( | )`body |
|
||||||
| ^
|
| ^
|
||||||
|
@ -949,7 +949,7 @@ LL | /// | table\`( | )`body |
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: unescaped backtick
|
error: unescaped backtick
|
||||||
--> $DIR/unescaped_backticks.rs:177:18
|
--> $DIR/unescaped_backticks.rs:178:18
|
||||||
|
|
|
|
||||||
LL | /// | table`( | )`body |
|
LL | /// | table`( | )`body |
|
||||||
| ^
|
| ^
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#![crate_name = "foo"]
|
#![crate_name = "foo"]
|
||||||
|
#![allow(rustdoc::redundant_explicit_links)]
|
||||||
//! # Description test crate
|
//! # Description test crate
|
||||||
//!
|
//!
|
||||||
//! This is the contents of the test crate docstring.
|
//! This is the contents of the test crate docstring.
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#![allow(rustdoc::redundant_explicit_links)]
|
||||||
|
|
||||||
// @has basic/index.html
|
// @has basic/index.html
|
||||||
// @has - '//a/@href' 'struct.ThisType.html'
|
// @has - '//a/@href' 'struct.ThisType.html'
|
||||||
// @has - '//a/@title' 'struct basic::ThisType'
|
// @has - '//a/@title' 'struct basic::ThisType'
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// ignore-tidy-linelength
|
// ignore-tidy-linelength
|
||||||
|
|
||||||
#![crate_name = "foo"]
|
#![crate_name = "foo"]
|
||||||
|
#![allow(rustdoc::redundant_explicit_links)]
|
||||||
|
|
||||||
//! Here's a link to [`Vec<T>`] and one to [`Box<Vec<Option<T>>>`].
|
//! Here's a link to [`Vec<T>`] and one to [`Box<Vec<Option<T>>>`].
|
||||||
//! Here's a link to [`Iterator<Box<T>>::Item`].
|
//! Here's a link to [`Iterator<Box<T>>::Item`].
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#![deny(rustdoc::broken_intra_doc_links)]
|
#![deny(rustdoc::broken_intra_doc_links)]
|
||||||
|
#![allow(rustdoc::redundant_explicit_links)]
|
||||||
|
|
||||||
pub struct S;
|
pub struct S;
|
||||||
pub mod char {}
|
pub mod char {}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue