refactor and reword intra-doc link errors

This commit refactors intra-doc link error reporting to deduplicate code
and decouple error construction from the type of error. This greatly
improves flexibility at each error construction site, while reducing the
complexity of the diagnostic creation.

This commit also rewords the diagnostics for clarity and style:

- Diagnostics should not end in periods.
- It's unnecessary to say "ignoring it". Since this is a warning by
  default, it's already clear that the link is ignored.
This commit is contained in:
Andy Russell 2020-07-19 13:03:35 -04:00
parent 48036804d2
commit 7f3e2c0d37
No known key found for this signature in database
GPG key ID: BE2221033EDBC374
17 changed files with 290 additions and 298 deletions

View file

@ -1,5 +1,5 @@
use rustc_ast::ast;
use rustc_errors::Applicability;
use rustc_errors::{Applicability, DiagnosticBuilder};
use rustc_expand::base::SyntaxExtensionKind;
use rustc_feature::UnstableFeatures;
use rustc_hir as hir;
@ -45,7 +45,17 @@ pub fn collect_intra_doc_links(krate: Crate, cx: &DocContext<'_>) -> Crate {
enum ErrorKind {
ResolutionFailure,
AnchorFailure(&'static str),
AnchorFailure(AnchorFailure),
}
enum AnchorFailure {
MultipleAnchors,
Primitive,
Variant,
AssocConstant,
AssocType,
Field,
Method,
}
struct LinkCollector<'a, 'tcx> {
@ -197,9 +207,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
// Not a trait item; just return what we found.
Res::PrimTy(..) => {
if extra_fragment.is_some() {
return Err(ErrorKind::AnchorFailure(
"primitive types cannot be followed by anchors",
));
return Err(ErrorKind::AnchorFailure(AnchorFailure::Primitive));
}
return Ok((res, Some(path_str.to_owned())));
}
@ -209,9 +217,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
if disambiguator == Some("type") {
if let Some(prim) = is_primitive(path_str, ns) {
if extra_fragment.is_some() {
return Err(ErrorKind::AnchorFailure(
"primitive types cannot be followed by anchors",
));
return Err(ErrorKind::AnchorFailure(AnchorFailure::Primitive));
}
return Ok((prim, Some(path_str.to_owned())));
}
@ -228,9 +234,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
}
} else if let Some(prim) = is_primitive(path_str, ns) {
if extra_fragment.is_some() {
return Err(ErrorKind::AnchorFailure(
"primitive types cannot be followed by anchors",
));
return Err(ErrorKind::AnchorFailure(AnchorFailure::Primitive));
}
return Ok((prim, Some(path_str.to_owned())));
} else {
@ -338,9 +342,9 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
};
if extra_fragment.is_some() {
Err(ErrorKind::AnchorFailure(if item.kind == ty::AssocKind::Fn {
"methods cannot be followed by anchors"
AnchorFailure::Method
} else {
"associated constants cannot be followed by anchors"
AnchorFailure::AssocConstant
}))
} else {
Ok((ty_res, Some(format!("{}.{}", out, item_name))))
@ -358,9 +362,9 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
} {
if extra_fragment.is_some() {
Err(ErrorKind::AnchorFailure(if def.is_enum() {
"enum variants cannot be followed by anchors"
AnchorFailure::Variant
} else {
"struct fields cannot be followed by anchors"
AnchorFailure::Field
}))
} else {
Ok((
@ -404,11 +408,11 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
if extra_fragment.is_some() {
Err(ErrorKind::AnchorFailure(if item.kind == ty::AssocKind::Const {
"associated constants cannot be followed by anchors"
AnchorFailure::AssocConstant
} else if item.kind == ty::AssocKind::Type {
"associated types cannot be followed by anchors"
AnchorFailure::AssocType
} else {
"methods cannot be followed by anchors"
AnchorFailure::Method
}))
} else {
Ok((ty_res, Some(format!("{}.{}", kind, item_name))))
@ -559,16 +563,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
let link = ori_link.replace("`", "");
let parts = link.split('#').collect::<Vec<_>>();
let (link, extra_fragment) = if parts.len() > 2 {
build_diagnostic(
cx,
&item,
&link,
&dox,
link_range,
"has an issue with the link anchor.",
"only one `#` is allowed in a link",
None,
);
anchor_failure(cx, &item, &link, &dox, link_range, AnchorFailure::MultipleAnchors);
continue;
} else if parts.len() == 2 {
if parts[0].trim().is_empty() {
@ -803,21 +798,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
&& (item.visibility == Visibility::Public)
&& !self.cx.render_options.document_private
{
let item_name = item.name.as_deref().unwrap_or("<unknown>");
let err_msg = format!(
"public documentation for `{}` links to a private item",
item_name
);
build_diagnostic(
cx,
&item,
path_str,
&dox,
link_range,
&err_msg,
"this item is private",
None,
);
privacy_error(cx, &item, &path_str, &dox, link_range);
continue;
}
}
@ -851,24 +832,33 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
}
}
fn build_diagnostic(
/// Reports a diagnostic for an intra-doc link.
///
/// If no link range is provided, or the source span of the link cannot be determined, the span of
/// the entire documentation block is used for the lint. If a range is provided but the span
/// calculation fails, a note is added to the diagnostic pointing to the link in the markdown.
///
/// The `decorate` callback is invoked in all cases to allow further customization of the
/// diagnostic before emission. If the span of the link was able to be determined, the second
/// parameter of the callback will contain it, and the primary span of the diagnostic will be set
/// to it.
fn report_diagnostic(
cx: &DocContext<'_>,
msg: &str,
item: &Item,
path_str: &str,
dox: &str,
link_range: Option<Range<usize>>,
err_msg: &str,
short_err_msg: &str,
help_msg: Option<&str>,
decorate: impl FnOnce(&mut DiagnosticBuilder<'_>, Option<rustc_span::Span>),
) {
let hir_id = match cx.as_local_hir_id(item.def_id) {
Some(hir_id) => hir_id,
None => {
// If non-local, no need to check anything.
info!("ignoring warning from parent crate: {}", err_msg);
info!("ignoring warning from parent crate: {}", msg);
return;
}
};
let attrs = &item.attrs;
let sp = span_of_attrs(attrs).unwrap_or(item.source.span());
@ -877,12 +867,15 @@ fn build_diagnostic(
hir_id,
sp,
|lint| {
let mut diag = lint.build(&format!("`[{}]` {}", path_str, err_msg));
let mut diag = lint.build(msg);
let span = link_range
.as_ref()
.and_then(|range| super::source_span_for_markdown_range(cx, dox, range, attrs));
if let Some(link_range) = link_range {
if let Some(sp) = super::source_span_for_markdown_range(cx, dox, &link_range, attrs)
{
if let Some(sp) = span {
diag.set_span(sp);
diag.span_label(sp, short_err_msg);
} else {
// blah blah blah\nblah\nblah [blah] blah blah\nblah blah
// ^ ~~~~
@ -902,20 +895,15 @@ fn build_diagnostic(
found = link_range.len(),
));
}
};
if let Some(help_msg) = help_msg {
diag.help(help_msg);
}
decorate(&mut diag, span);
diag.emit();
},
);
}
/// Reports a resolution failure diagnostic.
///
/// If we cannot find the exact source span of the resolution failure, we use the span of the
/// documentation attributes themselves. This is a little heavy-handed, so we display the markdown
/// line containing the failure as a note as well.
fn resolution_failure(
cx: &DocContext<'_>,
item: &Item,
@ -923,15 +911,19 @@ fn resolution_failure(
dox: &str,
link_range: Option<Range<usize>>,
) {
build_diagnostic(
report_diagnostic(
cx,
&format!("unresolved link to `{}`", path_str),
item,
path_str,
dox,
link_range,
"cannot be resolved, ignoring it.",
"cannot be resolved, ignoring",
Some("to escape `[` and `]` characters, just add '\\' before them like `\\[` or `\\]`"),
|diag, sp| {
if let Some(sp) = sp {
diag.span_label(sp, "unresolved link");
}
diag.help(r#"to escape `[` and `]` characters, add '\' before them like `\[` or `\]`"#);
},
);
}
@ -941,18 +933,39 @@ fn anchor_failure(
path_str: &str,
dox: &str,
link_range: Option<Range<usize>>,
msg: &str,
failure: AnchorFailure,
) {
build_diagnostic(
cx,
item,
path_str,
dox,
link_range,
"has an issue with the link anchor.",
msg,
None,
);
let msg = match failure {
AnchorFailure::MultipleAnchors => format!("`{}` contains multiple anchors", path_str),
AnchorFailure::Primitive
| AnchorFailure::Variant
| AnchorFailure::AssocConstant
| AnchorFailure::AssocType
| AnchorFailure::Field
| AnchorFailure::Method => {
let kind = match failure {
AnchorFailure::Primitive => "primitive type",
AnchorFailure::Variant => "enum variant",
AnchorFailure::AssocConstant => "associated constant",
AnchorFailure::AssocType => "associated type",
AnchorFailure::Field => "struct field",
AnchorFailure::Method => "method",
AnchorFailure::MultipleAnchors => unreachable!("should be handled already"),
};
format!(
"`{}` contains an anchor, but links to {kind}s are already anchored",
path_str,
kind = kind
)
}
};
report_diagnostic(cx, &msg, item, dox, link_range, |diag, sp| {
if let Some(sp) = sp {
diag.span_label(sp, "contains invalid anchor");
}
});
}
fn ambiguity_error(
@ -963,121 +976,100 @@ fn ambiguity_error(
link_range: Option<Range<usize>>,
candidates: PerNS<Option<Res>>,
) {
let hir_id = match cx.as_local_hir_id(item.def_id) {
Some(hir_id) => hir_id,
None => {
// If non-local, no need to check anything.
return;
let mut msg = format!("`{}` is ", path_str);
let candidates = [TypeNS, ValueNS, MacroNS]
.iter()
.filter_map(|&ns| candidates[ns].map(|res| (res, ns)))
.collect::<Vec<_>>();
match candidates.as_slice() {
[(first_def, _), (second_def, _)] => {
msg += &format!(
"both {} {} and {} {}",
first_def.article(),
first_def.descr(),
second_def.article(),
second_def.descr(),
);
}
};
let attrs = &item.attrs;
let sp = span_of_attrs(attrs).unwrap_or(item.source.span());
cx.tcx.struct_span_lint_hir(
lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE,
hir_id,
sp,
|lint| {
let mut msg = format!("`{}` is ", path_str);
let candidates = [TypeNS, ValueNS, MacroNS]
.iter()
.filter_map(|&ns| candidates[ns].map(|res| (res, ns)))
.collect::<Vec<_>>();
match candidates.as_slice() {
[(first_def, _), (second_def, _)] => {
msg += &format!(
"both {} {} and {} {}",
first_def.article(),
first_def.descr(),
second_def.article(),
second_def.descr(),
);
}
_ => {
let mut candidates = candidates.iter().peekable();
while let Some((res, _)) = candidates.next() {
if candidates.peek().is_some() {
msg += &format!("{} {}, ", res.article(), res.descr());
} else {
msg += &format!("and {} {}", res.article(), res.descr());
}
}
_ => {
let mut candidates = candidates.iter().peekable();
while let Some((res, _)) = candidates.next() {
if candidates.peek().is_some() {
msg += &format!("{} {}, ", res.article(), res.descr());
} else {
msg += &format!("and {} {}", res.article(), res.descr());
}
}
}
}
let mut diag = lint.build(&msg);
report_diagnostic(cx, &msg, item, dox, link_range.clone(), |diag, sp| {
if let Some(sp) = sp {
diag.span_label(sp, "ambiguous link");
if let Some(link_range) = link_range {
if let Some(sp) = super::source_span_for_markdown_range(cx, dox, &link_range, attrs)
{
diag.set_span(sp);
diag.span_label(sp, "ambiguous link");
let link_range = link_range.expect("must have a link range if we have a span");
for (res, ns) in candidates {
let (action, mut suggestion) = match res {
Res::Def(DefKind::AssocFn | DefKind::Fn, _) => {
("add parentheses", format!("{}()", path_str))
}
Res::Def(DefKind::Macro(MacroKind::Bang), _) => {
("add an exclamation mark", format!("{}!", path_str))
}
_ => {
let type_ = match (res, ns) {
(Res::Def(DefKind::Const, _), _) => "const",
(Res::Def(DefKind::Static, _), _) => "static",
(Res::Def(DefKind::Struct, _), _) => "struct",
(Res::Def(DefKind::Enum, _), _) => "enum",
(Res::Def(DefKind::Union, _), _) => "union",
(Res::Def(DefKind::Trait, _), _) => "trait",
(Res::Def(DefKind::Mod, _), _) => "module",
(_, TypeNS) => "type",
(_, ValueNS) => "value",
(Res::Def(DefKind::Macro(MacroKind::Derive), _), MacroNS) => {
"derive"
}
(_, MacroNS) => "macro",
};
// FIXME: if this is an implied shortcut link, it's bad style to suggest `@`
("prefix with the item type", format!("{}@{}", type_, path_str))
}
for (res, ns) in candidates {
let (action, mut suggestion) = match res {
Res::Def(DefKind::AssocFn | DefKind::Fn, _) => {
("add parentheses", format!("{}()", path_str))
}
Res::Def(DefKind::Macro(MacroKind::Bang), _) => {
("add an exclamation mark", format!("{}!", path_str))
}
_ => {
let type_ = match (res, ns) {
(Res::Def(DefKind::Const, _), _) => "const",
(Res::Def(DefKind::Static, _), _) => "static",
(Res::Def(DefKind::Struct, _), _) => "struct",
(Res::Def(DefKind::Enum, _), _) => "enum",
(Res::Def(DefKind::Union, _), _) => "union",
(Res::Def(DefKind::Trait, _), _) => "trait",
(Res::Def(DefKind::Mod, _), _) => "module",
(_, TypeNS) => "type",
(_, ValueNS) => "value",
(Res::Def(DefKind::Macro(MacroKind::Derive), _), MacroNS) => "derive",
(_, MacroNS) => "macro",
};
if dox.bytes().nth(link_range.start) == Some(b'`') {
suggestion = format!("`{}`", suggestion);
}
diag.span_suggestion(
sp,
&format!("to link to the {}, {}", res.descr(), action),
suggestion,
Applicability::MaybeIncorrect,
);
// FIXME: if this is an implied shortcut link, it's bad style to suggest `@`
("prefix with the item type", format!("{}@{}", type_, path_str))
}
} else {
// blah blah blah\nblah\nblah [blah] blah blah\nblah blah
// ^ ~~~~
// | link_range
// last_new_line_offset
let last_new_line_offset =
dox[..link_range.start].rfind('\n').map_or(0, |n| n + 1);
let line = dox[last_new_line_offset..].lines().next().unwrap_or("");
};
// Print the line containing the `link_range` and manually mark it with '^'s.
diag.note(&format!(
"the link appears in this line:\n\n{line}\n\
{indicator: <before$}{indicator:^<found$}",
line = line,
indicator = "",
before = link_range.start - last_new_line_offset,
found = link_range.len(),
));
if dox.bytes().nth(link_range.start) == Some(b'`') {
suggestion = format!("`{}`", suggestion);
}
// FIXME: Create a version of this suggestion for when we don't have the span.
diag.span_suggestion(
sp,
&format!("to link to the {}, {}", res.descr(), action),
suggestion,
Applicability::MaybeIncorrect,
);
}
diag.emit();
},
);
}
});
}
fn privacy_error(
cx: &DocContext<'_>,
item: &Item,
path_str: &str,
dox: &str,
link_range: Option<Range<usize>>,
) {
let item_name = item.name.as_deref().unwrap_or("<unknown>");
let msg =
format!("public documentation for `{}` links to private item `{}`", item_name, path_str);
report_diagnostic(cx, &msg, item, dox, link_range, |diag, sp| {
if let Some(sp) = sp {
diag.span_label(sp, "this item is private");
}
});
}
/// Given an enum variant's res, return the res of its enum and the associated fragment.
@ -1089,7 +1081,7 @@ fn handle_variant(
use rustc_middle::ty::DefIdTree;
if extra_fragment.is_some() {
return Err(ErrorKind::AnchorFailure("variants cannot be followed by anchors"));
return Err(ErrorKind::AnchorFailure(AnchorFailure::Variant));
}
let parent = if let Some(parent) = cx.tcx.parent(res.def_id()) {
parent

View file

@ -1,15 +1,15 @@
error: `[v2]` cannot be resolved, ignoring it.
error: unresolved link to `v2`
--> $DIR/deny-intra-link-resolution-failure.rs:3:6
|
LL | /// [v2]
| ^^ cannot be resolved, ignoring
| ^^ unresolved link
|
note: the lint level is defined here
--> $DIR/deny-intra-link-resolution-failure.rs:1:9
|
LL | #![deny(intra_doc_link_resolution_failure)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
error: aborting due to previous error

View file

@ -1,15 +1,15 @@
error: `[TypeAlias::hoge]` cannot be resolved, ignoring it.
error: unresolved link to `TypeAlias::hoge`
--> $DIR/intra-doc-alias-ice.rs:5:30
|
LL | /// [broken cross-reference](TypeAlias::hoge)
| ^^^^^^^^^^^^^^^ cannot be resolved, ignoring
| ^^^^^^^^^^^^^^^ unresolved link
|
note: the lint level is defined here
--> $DIR/intra-doc-alias-ice.rs:1:9
|
LL | #![deny(intra_doc_link_resolution_failure)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
error: aborting due to previous error

View file

@ -7,7 +7,7 @@
/// ## For example:
///
/// arr[i]
//~^ ERROR `[i]` cannot be resolved, ignoring it.
//~^ ERROR `i`
pub fn test_ice() {
unimplemented!();
}

View file

@ -1,15 +1,15 @@
error: `[i]` cannot be resolved, ignoring it.
error: unresolved link to `i`
--> $DIR/intra-link-span-ice-55723.rs:9:10
|
LL | /// arr[i]
| ^ cannot be resolved, ignoring
| ^ unresolved link
|
note: the lint level is defined here
--> $DIR/intra-link-span-ice-55723.rs:1:9
|
LL | #![deny(intra_doc_link_resolution_failure)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
error: aborting due to previous error

View file

@ -23,23 +23,23 @@ pub enum Enum {
/// Like [Foo#hola].
///
/// Or maybe [Foo::f#hola].
//~^ ERROR `[Foo::f#hola]` has an issue with the link anchor.
//~^ ERROR `Foo::f#hola` contains an anchor
pub fn foo() {}
/// Empty.
///
/// Another anchor error: [hello#people#!].
//~^ ERROR `[hello#people#!]` has an issue with the link anchor.
//~^ ERROR `hello#people#!` contains multiple anchors
pub fn bar() {}
/// Empty?
///
/// Damn enum's variants: [Enum::A#whatever].
//~^ ERROR `[Enum::A#whatever]` has an issue with the link anchor.
//~^ ERROR `Enum::A#whatever` contains an anchor
pub fn enum_link() {}
/// Primitives?
///
/// [u32#hello]
//~^ ERROR `[u32#hello]` has an issue with the link anchor.
//~^ ERROR `u32#hello` contains an anchor
pub fn x() {}

View file

@ -1,8 +1,8 @@
error: `[Foo::f#hola]` has an issue with the link anchor.
error: `Foo::f#hola` contains an anchor, but links to struct fields are already anchored
--> $DIR/intra-links-anchors.rs:25:15
|
LL | /// Or maybe [Foo::f#hola].
| ^^^^^^^^^^^ struct fields cannot be followed by anchors
| ^^^^^^^^^^^ contains invalid anchor
|
note: the lint level is defined here
--> $DIR/intra-links-anchors.rs:1:9
@ -10,23 +10,23 @@ note: the lint level is defined here
LL | #![deny(intra_doc_link_resolution_failure)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: `[hello#people#!]` has an issue with the link anchor.
error: `hello#people#!` contains multiple anchors
--> $DIR/intra-links-anchors.rs:31:28
|
LL | /// Another anchor error: [hello#people#!].
| ^^^^^^^^^^^^^^ only one `#` is allowed in a link
| ^^^^^^^^^^^^^^ contains invalid anchor
error: `[Enum::A#whatever]` has an issue with the link anchor.
error: `Enum::A#whatever` contains an anchor, but links to enum variants are already anchored
--> $DIR/intra-links-anchors.rs:37:28
|
LL | /// Damn enum's variants: [Enum::A#whatever].
| ^^^^^^^^^^^^^^^^ variants cannot be followed by anchors
| ^^^^^^^^^^^^^^^^ contains invalid anchor
error: `[u32#hello]` has an issue with the link anchor.
error: `u32#hello` contains an anchor, but links to primitive types are already anchored
--> $DIR/intra-links-anchors.rs:43:6
|
LL | /// [u32#hello]
| ^^^^^^^^^ primitive types cannot be followed by anchors
| ^^^^^^^^^ contains invalid anchor
error: aborting due to 4 previous errors

View file

@ -1,4 +1,4 @@
warning: `[DontDocMe]` public documentation for `DocMe` links to a private item
warning: public documentation for `DocMe` links to private item `DontDocMe`
--> $DIR/intra-links-private.rs:6:11
|
LL | /// docs [DontDocMe]

View file

@ -4,7 +4,7 @@
#![cfg_attr(private, deny(intra_doc_link_resolution_failure))]
/// docs [DontDocMe]
//[public]~^ WARNING `[DontDocMe]` public documentation for `DocMe` links to a private item
//[public]~^ WARNING public documentation for `DocMe` links to private item `DontDocMe`
// FIXME: for [private] we should also make sure the link was actually generated
pub struct DocMe;
struct DontDocMe;

View file

@ -6,16 +6,16 @@
/// [error]
pub struct A;
//~^^ WARNING `[error]` cannot be resolved
//~^^ WARNING `error`
///
/// docs [error1]
//~^ WARNING `[error1]` cannot be resolved
//~^ WARNING `error1`
/// docs [error2]
///
pub struct B;
//~^^^ WARNING `[error2]` cannot be resolved
//~^^^ WARNING `error2`
/**
* This is a multi-line comment.
@ -23,4 +23,4 @@ pub struct B;
* It also has an [error].
*/
pub struct C;
//~^^^ WARNING `[error]` cannot be resolved
//~^^^ WARNING `error`

View file

@ -1,35 +1,35 @@
warning: `[error]` cannot be resolved, ignoring it.
warning: unresolved link to `error`
--> $DIR/intra-links-warning-crlf.rs:7:6
|
LL | /// [error]
| ^^^^^ cannot be resolved, ignoring
| ^^^^^ unresolved link
|
= note: `#[warn(intra_doc_link_resolution_failure)]` on by default
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
warning: `[error1]` cannot be resolved, ignoring it.
warning: unresolved link to `error1`
--> $DIR/intra-links-warning-crlf.rs:12:11
|
LL | /// docs [error1]
| ^^^^^^ cannot be resolved, ignoring
| ^^^^^^ unresolved link
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
warning: `[error2]` cannot be resolved, ignoring it.
warning: unresolved link to `error2`
--> $DIR/intra-links-warning-crlf.rs:15:11
|
LL | /// docs [error2]
| ^^^^^^ cannot be resolved, ignoring
| ^^^^^^ unresolved link
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
warning: `[error]` cannot be resolved, ignoring it.
warning: unresolved link to `error`
--> $DIR/intra-links-warning-crlf.rs:23:20
|
LL | * It also has an [error].
| ^^^^^ cannot be resolved, ignoring
| ^^^^^ unresolved link
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
warning: 4 warnings emitted

View file

@ -1,37 +1,37 @@
// check-pass
//! Test with [Foo::baz], [Bar::foo], ...
//~^ WARNING `[Foo::baz]` cannot be resolved
//~| WARNING `[Bar::foo]` cannot be resolved
//~^ WARNING `Foo::baz`
//~| WARNING `Bar::foo`
//! , [Uniooon::X] and [Qux::Z].
//~^ WARNING `[Uniooon::X]` cannot be resolved
//~| WARNING `[Qux::Z]` cannot be resolved
//~^ WARNING `Uniooon::X`
//~| WARNING `Qux::Z`
//!
//! , [Uniooon::X] and [Qux::Z].
//~^ WARNING `[Uniooon::X]` cannot be resolved
//~| WARNING `[Qux::Z]` cannot be resolved
//~^ WARNING `Uniooon::X`
//~| WARNING `Qux::Z`
/// [Qux:Y]
//~^ WARNING `[Qux:Y]` cannot be resolved
//~^ WARNING `Qux:Y`
pub struct Foo {
pub bar: usize,
}
/// Foo
/// bar [BarA] bar //~ WARNING `[BarA]` cannot be resolved
/// bar [BarA] bar //~ WARNING `BarA`
/// baz
pub fn a() {}
/**
* Foo
* bar [BarB] bar //~ WARNING `[BarB]` cannot be resolved
* bar [BarB] bar //~ WARNING `BarB`
* baz
*/
pub fn b() {}
/** Foo
bar [BarC] bar //~ WARNING `[BarC]` cannot be resolved
bar [BarC] bar //~ WARNING `BarC`
baz
let bar_c_1 = 0;
@ -42,12 +42,12 @@ baz
*/
pub fn c() {}
#[doc = "Foo\nbar [BarD] bar\nbaz"] //~ WARNING `[BarD]` cannot be resolved
#[doc = "Foo\nbar [BarD] bar\nbaz"] //~ WARNING `BarD`
pub fn d() {}
macro_rules! f {
($f:expr) => {
#[doc = $f] //~ WARNING `[BarF]` cannot be resolved
#[doc = $f] //~ WARNING `BarF`
pub fn f() {}
}
}
@ -55,30 +55,30 @@ f!("Foo\nbar [BarF] bar\nbaz");
/** # for example,
*
* time to introduce a link [error]*/ //~ WARNING `[error]` cannot be resolved
* time to introduce a link [error]*/ //~ WARNING `error`
pub struct A;
/**
* # for example,
*
* time to introduce a link [error] //~ WARNING `[error]` cannot be resolved
* time to introduce a link [error] //~ WARNING `error`
*/
pub struct B;
#[doc = "single line [error]"] //~ WARNING `[error]` cannot be resolved
#[doc = "single line [error]"] //~ WARNING `error`
pub struct C;
#[doc = "single line with \"escaping\" [error]"] //~ WARNING `[error]` cannot be resolved
#[doc = "single line with \"escaping\" [error]"] //~ WARNING `error`
pub struct D;
/// Item docs. //~ WARNING `[error]` cannot be resolved
/// Item docs. //~ WARNING `error`
#[doc="Hello there!"]
/// [error]
pub struct E;
///
/// docs [error1] //~ WARNING `[error1]` cannot be resolved
/// docs [error1] //~ WARNING `error1`
/// docs [error2] //~ WARNING `[error2]` cannot be resolved
/// docs [error2] //~ WARNING `error2`
///
pub struct F;

View file

@ -1,77 +1,77 @@
warning: `[Foo::baz]` cannot be resolved, ignoring it.
warning: unresolved link to `Foo::baz`
--> $DIR/intra-links-warning.rs:3:23
|
LL | //! Test with [Foo::baz], [Bar::foo], ...
| ^^^^^^^^ cannot be resolved, ignoring
| ^^^^^^^^ unresolved link
|
= note: `#[warn(intra_doc_link_resolution_failure)]` on by default
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
warning: `[Bar::foo]` cannot be resolved, ignoring it.
warning: unresolved link to `Bar::foo`
--> $DIR/intra-links-warning.rs:3:35
|
LL | //! Test with [Foo::baz], [Bar::foo], ...
| ^^^^^^^^ cannot be resolved, ignoring
| ^^^^^^^^ unresolved link
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
warning: `[Uniooon::X]` cannot be resolved, ignoring it.
warning: unresolved link to `Uniooon::X`
--> $DIR/intra-links-warning.rs:6:13
|
LL | //! , [Uniooon::X] and [Qux::Z].
| ^^^^^^^^^^ cannot be resolved, ignoring
| ^^^^^^^^^^ unresolved link
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
warning: `[Qux::Z]` cannot be resolved, ignoring it.
warning: unresolved link to `Qux::Z`
--> $DIR/intra-links-warning.rs:6:30
|
LL | //! , [Uniooon::X] and [Qux::Z].
| ^^^^^^ cannot be resolved, ignoring
| ^^^^^^ unresolved link
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
warning: `[Uniooon::X]` cannot be resolved, ignoring it.
warning: unresolved link to `Uniooon::X`
--> $DIR/intra-links-warning.rs:10:14
|
LL | //! , [Uniooon::X] and [Qux::Z].
| ^^^^^^^^^^ cannot be resolved, ignoring
| ^^^^^^^^^^ unresolved link
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
warning: `[Qux::Z]` cannot be resolved, ignoring it.
warning: unresolved link to `Qux::Z`
--> $DIR/intra-links-warning.rs:10:31
|
LL | //! , [Uniooon::X] and [Qux::Z].
| ^^^^^^ cannot be resolved, ignoring
| ^^^^^^ unresolved link
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
warning: `[Qux:Y]` cannot be resolved, ignoring it.
warning: unresolved link to `Qux:Y`
--> $DIR/intra-links-warning.rs:14:13
|
LL | /// [Qux:Y]
| ^^^^^ cannot be resolved, ignoring
| ^^^^^ unresolved link
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
warning: `[error]` cannot be resolved, ignoring it.
warning: unresolved link to `error`
--> $DIR/intra-links-warning.rs:58:30
|
LL | * time to introduce a link [error]*/
| ^^^^^ cannot be resolved, ignoring
| ^^^^^ unresolved link
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
warning: `[error]` cannot be resolved, ignoring it.
warning: unresolved link to `error`
--> $DIR/intra-links-warning.rs:64:30
|
LL | * time to introduce a link [error]
| ^^^^^ cannot be resolved, ignoring
| ^^^^^ unresolved link
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
warning: `[error]` cannot be resolved, ignoring it.
warning: unresolved link to `error`
--> $DIR/intra-links-warning.rs:68:1
|
LL | #[doc = "single line [error]"]
@ -81,9 +81,9 @@ LL | #[doc = "single line [error]"]
single line [error]
^^^^^
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
warning: `[error]` cannot be resolved, ignoring it.
warning: unresolved link to `error`
--> $DIR/intra-links-warning.rs:71:1
|
LL | #[doc = "single line with \"escaping\" [error]"]
@ -93,9 +93,9 @@ LL | #[doc = "single line with \"escaping\" [error]"]
single line with "escaping" [error]
^^^^^
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
warning: `[error]` cannot be resolved, ignoring it.
warning: unresolved link to `error`
--> $DIR/intra-links-warning.rs:74:1
|
LL | / /// Item docs.
@ -107,49 +107,49 @@ LL | | /// [error]
[error]
^^^^^
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
warning: `[error1]` cannot be resolved, ignoring it.
warning: unresolved link to `error1`
--> $DIR/intra-links-warning.rs:80:11
|
LL | /// docs [error1]
| ^^^^^^ cannot be resolved, ignoring
| ^^^^^^ unresolved link
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
warning: `[error2]` cannot be resolved, ignoring it.
warning: unresolved link to `error2`
--> $DIR/intra-links-warning.rs:82:11
|
LL | /// docs [error2]
| ^^^^^^ cannot be resolved, ignoring
| ^^^^^^ unresolved link
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
warning: `[BarA]` cannot be resolved, ignoring it.
warning: unresolved link to `BarA`
--> $DIR/intra-links-warning.rs:21:10
|
LL | /// bar [BarA] bar
| ^^^^ cannot be resolved, ignoring
| ^^^^ unresolved link
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
warning: `[BarB]` cannot be resolved, ignoring it.
warning: unresolved link to `BarB`
--> $DIR/intra-links-warning.rs:27:9
|
LL | * bar [BarB] bar
| ^^^^ cannot be resolved, ignoring
| ^^^^ unresolved link
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
warning: `[BarC]` cannot be resolved, ignoring it.
warning: unresolved link to `BarC`
--> $DIR/intra-links-warning.rs:34:6
|
LL | bar [BarC] bar
| ^^^^ cannot be resolved, ignoring
| ^^^^ unresolved link
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
warning: `[BarD]` cannot be resolved, ignoring it.
warning: unresolved link to `BarD`
--> $DIR/intra-links-warning.rs:45:1
|
LL | #[doc = "Foo\nbar [BarD] bar\nbaz"]
@ -159,9 +159,9 @@ LL | #[doc = "Foo\nbar [BarD] bar\nbaz"]
bar [BarD] bar
^^^^
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
warning: `[BarF]` cannot be resolved, ignoring it.
warning: unresolved link to `BarF`
--> $DIR/intra-links-warning.rs:50:9
|
LL | #[doc = $f]
@ -174,7 +174,7 @@ LL | f!("Foo\nbar [BarF] bar\nbaz");
bar [BarF] bar
^^^^
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
= note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
warning: 19 warnings emitted

View file

@ -1,4 +1,4 @@
warning: `[PrivateType]` public documentation for `public_item` links to a private item
warning: public documentation for `public_item` links to private item `PrivateType`
--> $DIR/issue-74134.rs:19:10
|
LL | /// [`PrivateType`]

View file

@ -17,7 +17,7 @@ pub struct PublicType;
pub struct Public {
/// [`PublicType`]
/// [`PrivateType`]
//[public]~^ WARNING public documentation for `public_item` links to a private
//[public]~^ WARNING public documentation for `public_item` links to private item `PrivateType`
pub public_item: u32,
/// [`PublicType`]

View file

@ -11,7 +11,7 @@
/// ```
/// println!("sup");
/// ```
pub fn link_error() {} //~^^^^^ ERROR cannot be resolved, ignoring it
pub fn link_error() {} //~^^^^^ ERROR unresolved link to `error`
/// wait, this doesn't have a doctest?
pub fn no_doctest() {} //~^ ERROR missing code example in this documentation

View file

@ -15,11 +15,11 @@ LL | #![deny(rustdoc)]
| ^^^^^^^
= note: `#[deny(private_doc_tests)]` implied by `#[deny(rustdoc)]`
error: `[error]` cannot be resolved, ignoring it.
error: unresolved link to `error`
--> $DIR/lint-group.rs:9:29
|
LL | /// what up, let's make an [error]
| ^^^^^ cannot be resolved, ignoring
| ^^^^^ unresolved link
|
note: the lint level is defined here
--> $DIR/lint-group.rs:7:9
@ -27,7 +27,7 @@ note: the lint level is defined here
LL | #![deny(rustdoc)]
| ^^^^^^^
= note: `#[deny(intra_doc_link_resolution_failure)]` implied by `#[deny(rustdoc)]`
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
error: missing code example in this documentation
--> $DIR/lint-group.rs:16:1