Disallow linking to items with a mismatched disambiguator
This commit is contained in:
parent
f042d749b0
commit
8e0e925e2b
@ -574,9 +574,9 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
|
||||
};
|
||||
let resolved_self;
|
||||
let mut path_str;
|
||||
let mut disambiguator = None;
|
||||
let (res, fragment) = {
|
||||
let mut kind = None;
|
||||
let mut disambiguator = None;
|
||||
path_str = if let Some(prefix) =
|
||||
["struct@", "enum@", "type@", "trait@", "union@", "module@", "mod@"]
|
||||
.iter()
|
||||
@ -595,6 +595,7 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
|
||||
link.trim_start_matches(prefix)
|
||||
} else if link.ends_with("!()") {
|
||||
kind = Some(MacroNS);
|
||||
disambiguator = Some("bang");
|
||||
link.trim_end_matches("!()")
|
||||
} else if link.ends_with("()") {
|
||||
kind = Some(ValueNS);
|
||||
@ -610,7 +611,7 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
|
||||
link.trim_start_matches("derive@")
|
||||
} else if link.ends_with('!') {
|
||||
kind = Some(MacroNS);
|
||||
disambiguator = Some("macro");
|
||||
disambiguator = Some("bang");
|
||||
link.trim_end_matches('!')
|
||||
} else {
|
||||
&link[..]
|
||||
@ -789,6 +790,46 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
|
||||
} else {
|
||||
debug!("intra-doc link to {} resolved to {:?}", path_str, res);
|
||||
|
||||
// Disallow e.g. linking to enums with `struct@`
|
||||
if let Res::Def(kind, id) = res {
|
||||
debug!("saw kind {:?} with disambiguator {:?}", kind, disambiguator);
|
||||
// NOTE: this relies on the fact that `''` is never parsed as a disambiguator
|
||||
// NOTE: this needs to be kept in sync with the disambiguator parsing
|
||||
match (kind, disambiguator.unwrap_or_default().trim_end_matches("@")) {
|
||||
| (DefKind::Struct, "struct")
|
||||
| (DefKind::Enum, "enum")
|
||||
| (DefKind::Trait, "trait")
|
||||
| (DefKind::Union, "union")
|
||||
| (DefKind::Mod, "mod" | "module")
|
||||
| (DefKind::Const | DefKind::ConstParam | DefKind::AssocConst | DefKind::AnonConst, "const")
|
||||
| (DefKind::Static, "static")
|
||||
// NOTE: this allows 'method' to mean both normal functions and associated functions
|
||||
// This can't cause ambiguity because both are in the same namespace.
|
||||
| (DefKind::Fn | DefKind::AssocFn, "fn" | "function" | "method")
|
||||
| (DefKind::Macro(MacroKind::Bang), "bang")
|
||||
| (DefKind::Macro(MacroKind::Derive), "derive")
|
||||
// These are namespaces; allow anything in the namespace to match
|
||||
| (_, "type" | "macro" | "value")
|
||||
// If no disambiguator given, allow anything
|
||||
| (_, "")
|
||||
// All of these are valid, so do nothing
|
||||
=> {}
|
||||
(_, disambiguator) => {
|
||||
// The resolved item did not match the disambiguator; give a better error than 'not found'
|
||||
let msg = format!("unresolved link to `{}`", path_str);
|
||||
report_diagnostic(cx, &msg, &item, &dox, link_range, |diag, sp| {
|
||||
let msg = format!("this item resolved to {} {}, which did not match the disambiguator '{}'", kind.article(), kind.descr(id), disambiguator);
|
||||
if let Some(sp) = sp {
|
||||
diag.span_note(sp, &msg);
|
||||
} else {
|
||||
diag.note(&msg);
|
||||
}
|
||||
});
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// item can be non-local e.g. when using #[doc(primitive = "pointer")]
|
||||
if let Some((src_id, dst_id)) = res
|
||||
.opt_def_id()
|
||||
|
53
src/test/rustdoc-ui/intra-links-disambiguator-mismatch.rs
Normal file
53
src/test/rustdoc-ui/intra-links-disambiguator-mismatch.rs
Normal file
@ -0,0 +1,53 @@
|
||||
#![deny(broken_intra_doc_links)]
|
||||
//~^ NOTE lint level is defined
|
||||
pub enum S {}
|
||||
|
||||
macro_rules! m {
|
||||
() => {};
|
||||
}
|
||||
|
||||
static s: usize = 0;
|
||||
const c: usize = 0;
|
||||
|
||||
trait T {}
|
||||
|
||||
/// Link to [struct@S]
|
||||
//~^ ERROR unresolved link to `S`
|
||||
//~| NOTE did not match
|
||||
|
||||
/// Link to [mod@S]
|
||||
//~^ ERROR unresolved link to `S`
|
||||
//~| NOTE did not match
|
||||
|
||||
/// Link to [union@S]
|
||||
//~^ ERROR unresolved link to `S`
|
||||
//~| NOTE did not match
|
||||
|
||||
/// Link to [trait@S]
|
||||
//~^ ERROR unresolved link to `S`
|
||||
//~| NOTE did not match
|
||||
|
||||
/// Link to [struct@T]
|
||||
//~^ ERROR unresolved link to `T`
|
||||
//~| NOTE did not match
|
||||
|
||||
/// Link to [derive@m]
|
||||
//~^ ERROR unresolved link to `m`
|
||||
//~| NOTE did not match
|
||||
|
||||
/// Link to [const@s]
|
||||
//~^ ERROR unresolved link to `s`
|
||||
//~| NOTE did not match
|
||||
|
||||
/// Link to [static@c]
|
||||
//~^ ERROR unresolved link to `c`
|
||||
//~| NOTE did not match
|
||||
|
||||
/// Link to [fn@c]
|
||||
//~^ ERROR unresolved link to `c`
|
||||
//~| NOTE did not match
|
||||
|
||||
/// Link to [c()]
|
||||
//~^ ERROR unresolved link to `c`
|
||||
//~| NOTE did not match
|
||||
pub fn f() {}
|
127
src/test/rustdoc-ui/intra-links-disambiguator-mismatch.stderr
Normal file
127
src/test/rustdoc-ui/intra-links-disambiguator-mismatch.stderr
Normal file
@ -0,0 +1,127 @@
|
||||
error: unresolved link to `S`
|
||||
--> $DIR/intra-links-disambiguator-mismatch.rs:16:14
|
||||
|
|
||||
LL | /// Link to [struct@S]
|
||||
| ^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/intra-links-disambiguator-mismatch.rs:1:9
|
||||
|
|
||||
LL | #![deny(broken_intra_doc_links)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: this item resolved to an enum, which did not match the disambiguator 'struct'
|
||||
--> $DIR/intra-links-disambiguator-mismatch.rs:16:14
|
||||
|
|
||||
LL | /// Link to [struct@S]
|
||||
| ^^^^^^^^
|
||||
|
||||
error: unresolved link to `S`
|
||||
--> $DIR/intra-links-disambiguator-mismatch.rs:20:14
|
||||
|
|
||||
LL | /// Link to [mod@S]
|
||||
| ^^^^^
|
||||
|
|
||||
note: this item resolved to an enum, which did not match the disambiguator 'mod'
|
||||
--> $DIR/intra-links-disambiguator-mismatch.rs:20:14
|
||||
|
|
||||
LL | /// Link to [mod@S]
|
||||
| ^^^^^
|
||||
|
||||
error: unresolved link to `S`
|
||||
--> $DIR/intra-links-disambiguator-mismatch.rs:24:14
|
||||
|
|
||||
LL | /// Link to [union@S]
|
||||
| ^^^^^^^
|
||||
|
|
||||
note: this item resolved to an enum, which did not match the disambiguator 'union'
|
||||
--> $DIR/intra-links-disambiguator-mismatch.rs:24:14
|
||||
|
|
||||
LL | /// Link to [union@S]
|
||||
| ^^^^^^^
|
||||
|
||||
error: unresolved link to `S`
|
||||
--> $DIR/intra-links-disambiguator-mismatch.rs:28:14
|
||||
|
|
||||
LL | /// Link to [trait@S]
|
||||
| ^^^^^^^
|
||||
|
|
||||
note: this item resolved to an enum, which did not match the disambiguator 'trait'
|
||||
--> $DIR/intra-links-disambiguator-mismatch.rs:28:14
|
||||
|
|
||||
LL | /// Link to [trait@S]
|
||||
| ^^^^^^^
|
||||
|
||||
error: unresolved link to `T`
|
||||
--> $DIR/intra-links-disambiguator-mismatch.rs:32:14
|
||||
|
|
||||
LL | /// Link to [struct@T]
|
||||
| ^^^^^^^^
|
||||
|
|
||||
note: this item resolved to a trait, which did not match the disambiguator 'struct'
|
||||
--> $DIR/intra-links-disambiguator-mismatch.rs:32:14
|
||||
|
|
||||
LL | /// Link to [struct@T]
|
||||
| ^^^^^^^^
|
||||
|
||||
error: unresolved link to `m`
|
||||
--> $DIR/intra-links-disambiguator-mismatch.rs:36:14
|
||||
|
|
||||
LL | /// Link to [derive@m]
|
||||
| ^^^^^^^^
|
||||
|
|
||||
note: this item resolved to a macro, which did not match the disambiguator 'derive'
|
||||
--> $DIR/intra-links-disambiguator-mismatch.rs:36:14
|
||||
|
|
||||
LL | /// Link to [derive@m]
|
||||
| ^^^^^^^^
|
||||
|
||||
error: unresolved link to `s`
|
||||
--> $DIR/intra-links-disambiguator-mismatch.rs:40:14
|
||||
|
|
||||
LL | /// Link to [const@s]
|
||||
| ^^^^^^^
|
||||
|
|
||||
note: this item resolved to a static, which did not match the disambiguator 'const'
|
||||
--> $DIR/intra-links-disambiguator-mismatch.rs:40:14
|
||||
|
|
||||
LL | /// Link to [const@s]
|
||||
| ^^^^^^^
|
||||
|
||||
error: unresolved link to `c`
|
||||
--> $DIR/intra-links-disambiguator-mismatch.rs:44:14
|
||||
|
|
||||
LL | /// Link to [static@c]
|
||||
| ^^^^^^^^
|
||||
|
|
||||
note: this item resolved to a constant, which did not match the disambiguator 'static'
|
||||
--> $DIR/intra-links-disambiguator-mismatch.rs:44:14
|
||||
|
|
||||
LL | /// Link to [static@c]
|
||||
| ^^^^^^^^
|
||||
|
||||
error: unresolved link to `c`
|
||||
--> $DIR/intra-links-disambiguator-mismatch.rs:48:14
|
||||
|
|
||||
LL | /// Link to [fn@c]
|
||||
| ^^^^
|
||||
|
|
||||
note: this item resolved to a constant, which did not match the disambiguator 'fn'
|
||||
--> $DIR/intra-links-disambiguator-mismatch.rs:48:14
|
||||
|
|
||||
LL | /// Link to [fn@c]
|
||||
| ^^^^
|
||||
|
||||
error: unresolved link to `c`
|
||||
--> $DIR/intra-links-disambiguator-mismatch.rs:52:14
|
||||
|
|
||||
LL | /// Link to [c()]
|
||||
| ^^^
|
||||
|
|
||||
note: this item resolved to a constant, which did not match the disambiguator 'fn'
|
||||
--> $DIR/intra-links-disambiguator-mismatch.rs:52:14
|
||||
|
|
||||
LL | /// Link to [c()]
|
||||
| ^^^
|
||||
|
||||
error: aborting due to 10 previous errors
|
||||
|
Loading…
Reference in New Issue
Block a user