Make errors more concise and helpful
Before: ``` = note: this link partially resolves to the struct `S` = note: no `fmt` in `S` ``` After: ``` = note: the struct `S` has no field or associated item named `fmt` ```
This commit is contained in:
parent
7b8d0befd6
commit
e2d69f2eb1
7 changed files with 81 additions and 65 deletions
|
@ -1406,11 +1406,18 @@ fn resolution_failure(
|
||||||
let in_scope = kinds.iter().any(|kind| kind.res().is_some());
|
let in_scope = kinds.iter().any(|kind| kind.res().is_some());
|
||||||
let mut reported_not_in_scope = false;
|
let mut reported_not_in_scope = false;
|
||||||
let item = |res: Res| {
|
let item = |res: Res| {
|
||||||
if let Some(id) = res.opt_def_id() {
|
format!("the {} `{}`", res.descr(), cx.tcx.item_name(res.def_id()).to_string())
|
||||||
(format!("the {} `{}`", res.descr(), cx.tcx.item_name(id).to_string()), ",")
|
};
|
||||||
} else {
|
let assoc_item_not_allowed = |res: Res, diag: &mut DiagnosticBuilder<'_>| {
|
||||||
(format!("{} {}", res.article(), res.descr()), "")
|
let def_id = res.def_id();
|
||||||
}
|
let name = cx.tcx.item_name(def_id);
|
||||||
|
let note = format!(
|
||||||
|
"`{}` is {} {}, not a module or type, and cannot have associated items",
|
||||||
|
name,
|
||||||
|
res.article(),
|
||||||
|
res.descr()
|
||||||
|
);
|
||||||
|
diag.note(¬e);
|
||||||
};
|
};
|
||||||
for failure in kinds {
|
for failure in kinds {
|
||||||
match failure {
|
match failure {
|
||||||
|
@ -1425,11 +1432,9 @@ fn resolution_failure(
|
||||||
}
|
}
|
||||||
ResolutionFailure::Dummy => continue,
|
ResolutionFailure::Dummy => continue,
|
||||||
ResolutionFailure::WrongNamespace(res, expected_ns) => {
|
ResolutionFailure::WrongNamespace(res, expected_ns) => {
|
||||||
let (item, comma) = item(res);
|
|
||||||
let note = format!(
|
let note = format!(
|
||||||
"this link resolves to {}{} which is not in the {} namespace",
|
"this link resolves to {}, which is not in the {} namespace",
|
||||||
item,
|
item(res),
|
||||||
comma,
|
|
||||||
expected_ns.descr()
|
expected_ns.descr()
|
||||||
);
|
);
|
||||||
diag.note(¬e);
|
diag.note(¬e);
|
||||||
|
@ -1450,10 +1455,9 @@ fn resolution_failure(
|
||||||
panic!("all intra doc links should have a parent item")
|
panic!("all intra doc links should have a parent item")
|
||||||
}
|
}
|
||||||
ResolutionFailure::NoPrimitiveImpl(res, _) => {
|
ResolutionFailure::NoPrimitiveImpl(res, _) => {
|
||||||
let (item, comma) = item(res);
|
|
||||||
let note = format!(
|
let note = format!(
|
||||||
"this link partially resolves to {}{} which does not have any associated items",
|
"this link partially resolves to {}, which does not have any associated items",
|
||||||
item, comma,
|
item(res),
|
||||||
);
|
);
|
||||||
diag.note(¬e);
|
diag.note(¬e);
|
||||||
}
|
}
|
||||||
|
@ -1465,41 +1469,62 @@ fn resolution_failure(
|
||||||
diag.note(¬e);
|
diag.note(¬e);
|
||||||
}
|
}
|
||||||
ResolutionFailure::NoAssocItem(res, assoc_item) => {
|
ResolutionFailure::NoAssocItem(res, assoc_item) => {
|
||||||
let (item, _) = item(res);
|
use DefKind::*;
|
||||||
diag.note(&format!("this link partially resolves to {}", item));
|
|
||||||
// FIXME: when are items neither a primitive nor a Def?
|
let (kind, def_id) = match res {
|
||||||
if let Res::Def(_, def_id) = res {
|
Res::Def(kind, def_id) => (kind, def_id),
|
||||||
let name = cx.tcx.item_name(def_id);
|
_ => unreachable!(
|
||||||
let note = format!("no `{}` in `{}`", assoc_item, name,);
|
"primitives are covered above and other `Res` variants aren't possible at module scope"
|
||||||
diag.note(¬e);
|
),
|
||||||
}
|
};
|
||||||
|
let name = cx.tcx.item_name(def_id);
|
||||||
|
let path_description = match kind {
|
||||||
|
Mod | ForeignMod => "inner item",
|
||||||
|
Struct => "field or associated item",
|
||||||
|
Enum | Union => "variant or associated item",
|
||||||
|
Variant
|
||||||
|
| Field
|
||||||
|
| Closure
|
||||||
|
| Generator
|
||||||
|
| AssocTy
|
||||||
|
| AssocConst
|
||||||
|
| AssocFn
|
||||||
|
| Fn
|
||||||
|
| Macro(_)
|
||||||
|
| Const
|
||||||
|
| ConstParam
|
||||||
|
| ExternCrate
|
||||||
|
| Use
|
||||||
|
| LifetimeParam
|
||||||
|
| Ctor(_, _)
|
||||||
|
| AnonConst => return assoc_item_not_allowed(res, diag),
|
||||||
|
Trait | TyAlias | ForeignTy | OpaqueTy | TraitAlias | TyParam
|
||||||
|
| Static => "associated item",
|
||||||
|
Impl | GlobalAsm => unreachable!("not a path"),
|
||||||
|
};
|
||||||
|
let note = format!(
|
||||||
|
"the {} `{}` has no {} named `{}`",
|
||||||
|
res.descr(),
|
||||||
|
name,
|
||||||
|
path_description,
|
||||||
|
assoc_item
|
||||||
|
);
|
||||||
|
diag.note(¬e);
|
||||||
}
|
}
|
||||||
ResolutionFailure::CannotHaveAssociatedItems(res, _) => {
|
ResolutionFailure::CannotHaveAssociatedItems(res, _) => {
|
||||||
let (item, _) = item(res);
|
assoc_item_not_allowed(res, diag)
|
||||||
diag.note(&format!("this link partially resolves to {}", item));
|
|
||||||
if let Res::Def(kind, def_id) = res {
|
|
||||||
let name = cx.tcx.item_name(def_id);
|
|
||||||
let note = format!(
|
|
||||||
"`{}` is {} {}, not a module or type, and cannot have associated items",
|
|
||||||
name,
|
|
||||||
kind.article(),
|
|
||||||
kind.descr(def_id)
|
|
||||||
);
|
|
||||||
diag.note(¬e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// TODO: is there ever a case where this happens?
|
// TODO: is there ever a case where this happens?
|
||||||
ResolutionFailure::NotAnEnum(res) => {
|
ResolutionFailure::NotAnEnum(res) => {
|
||||||
let (item, comma) = item(res);
|
|
||||||
let note =
|
let note =
|
||||||
format!("this link resolves to {}{} which is not an enum", item, comma);
|
format!("this link resolves to {}, which is not an enum", item(res));
|
||||||
diag.note(¬e);
|
diag.note(¬e);
|
||||||
diag.note("if this were an enum, it might have a variant which resolved");
|
diag.note("if this were an enum, it might have a variant which resolved");
|
||||||
}
|
}
|
||||||
ResolutionFailure::NotAVariant(res, variant) => {
|
ResolutionFailure::NotAVariant(res, variant) => {
|
||||||
let note = format!(
|
let note = format!(
|
||||||
"this link partially resolves to {}, but there is no variant named {}",
|
"this link partially resolves to {}, but there is no variant named {}",
|
||||||
item(res).0,
|
item(res),
|
||||||
variant
|
variant
|
||||||
);
|
);
|
||||||
diag.note(¬e);
|
diag.note(¬e);
|
||||||
|
|
|
@ -2,14 +2,14 @@ error: unresolved link to `S::fmt`
|
||||||
--> $DIR/assoc-item-not-in-scope.rs:4:14
|
--> $DIR/assoc-item-not-in-scope.rs:4:14
|
||||||
|
|
|
|
||||||
LL | /// Link to [`S::fmt`]
|
LL | /// Link to [`S::fmt`]
|
||||||
| ^^^^^^^^ unresolved link
|
| ^^^^^^^^
|
||||||
|
|
|
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/assoc-item-not-in-scope.rs:1:9
|
--> $DIR/assoc-item-not-in-scope.rs:1:9
|
||||||
|
|
|
|
||||||
LL | #![deny(broken_intra_doc_links)]
|
LL | #![deny(broken_intra_doc_links)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
|
= note: the struct `S` has no field or associated item named `fmt`
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,7 @@ note: the lint level is defined here
|
||||||
|
|
|
|
||||||
LL | #![deny(broken_intra_doc_links)]
|
LL | #![deny(broken_intra_doc_links)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= note: this link partially resolves to the type alias `TypeAlias`
|
= note: the type alias `TypeAlias` has no associated item named `hoge`
|
||||||
= note: no `hoge` in `TypeAlias`
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -12,23 +12,19 @@
|
||||||
|
|
||||||
/// [f::A]
|
/// [f::A]
|
||||||
//~^ ERROR unresolved link
|
//~^ ERROR unresolved link
|
||||||
//~| NOTE this link partially resolves
|
|
||||||
//~| NOTE `f` is a function, not a module
|
//~| NOTE `f` is a function, not a module
|
||||||
|
|
||||||
/// [S::A]
|
/// [S::A]
|
||||||
//~^ ERROR unresolved link
|
//~^ ERROR unresolved link
|
||||||
//~| NOTE this link partially resolves
|
//~| NOTE struct `S` has no field or associated item
|
||||||
//~| NOTE no `A` in `S`
|
|
||||||
|
|
||||||
/// [S::fmt]
|
/// [S::fmt]
|
||||||
//~^ ERROR unresolved link
|
//~^ ERROR unresolved link
|
||||||
//~| NOTE this link partially resolves
|
//~| NOTE struct `S` has no field or associated item
|
||||||
//~| NOTE no `fmt` in `S`
|
|
||||||
|
|
||||||
/// [E::D]
|
/// [E::D]
|
||||||
//~^ ERROR unresolved link
|
//~^ ERROR unresolved link
|
||||||
//~| NOTE this link partially resolves
|
//~| NOTE enum `E` has no variant or associated item
|
||||||
//~| NOTE no `D` in `E`
|
|
||||||
|
|
||||||
/// [u8::not_found]
|
/// [u8::not_found]
|
||||||
//~^ ERROR unresolved link
|
//~^ ERROR unresolved link
|
||||||
|
|
|
@ -13,43 +13,39 @@ LL | #![deny(broken_intra_doc_links)]
|
||||||
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
|
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
|
||||||
|
|
||||||
error: unresolved link to `f::A`
|
error: unresolved link to `f::A`
|
||||||
--> $DIR/intra-link-errors.rs:14:6
|
--> $DIR/intra-link-errors.rs:13:6
|
||||||
|
|
|
|
||||||
LL | /// [f::A]
|
LL | /// [f::A]
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
|
|
||||||
= note: this link partially resolves to the function `f`
|
|
||||||
= note: `f` is a function, not a module or type, and cannot have associated items
|
= note: `f` is a function, not a module or type, and cannot have associated items
|
||||||
|
|
||||||
error: unresolved link to `S::A`
|
error: unresolved link to `S::A`
|
||||||
--> $DIR/intra-link-errors.rs:19:6
|
--> $DIR/intra-link-errors.rs:17:6
|
||||||
|
|
|
|
||||||
LL | /// [S::A]
|
LL | /// [S::A]
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
|
|
||||||
= note: this link partially resolves to the struct `S`
|
= note: the struct `S` has no field or associated item named `A`
|
||||||
= note: no `A` in `S`
|
|
||||||
|
|
||||||
error: unresolved link to `S::fmt`
|
error: unresolved link to `S::fmt`
|
||||||
--> $DIR/intra-link-errors.rs:24:6
|
--> $DIR/intra-link-errors.rs:21:6
|
||||||
|
|
|
|
||||||
LL | /// [S::fmt]
|
LL | /// [S::fmt]
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
|
|
||||||
= note: this link partially resolves to the struct `S`
|
= note: the struct `S` has no field or associated item named `fmt`
|
||||||
= note: no `fmt` in `S`
|
|
||||||
|
|
||||||
error: unresolved link to `E::D`
|
error: unresolved link to `E::D`
|
||||||
--> $DIR/intra-link-errors.rs:29:6
|
--> $DIR/intra-link-errors.rs:25:6
|
||||||
|
|
|
|
||||||
LL | /// [E::D]
|
LL | /// [E::D]
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
|
|
||||||
= note: this link partially resolves to the enum `E`
|
= note: the enum `E` has no variant or associated item named `D`
|
||||||
= note: no `D` in `E`
|
|
||||||
|
|
||||||
error: unresolved link to `u8::not_found`
|
error: unresolved link to `u8::not_found`
|
||||||
--> $DIR/intra-link-errors.rs:34:6
|
--> $DIR/intra-link-errors.rs:29:6
|
||||||
|
|
|
|
||||||
LL | /// [u8::not_found]
|
LL | /// [u8::not_found]
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
|
@ -57,7 +53,7 @@ LL | /// [u8::not_found]
|
||||||
= note: the builtin type `u8` does not have an associated item named `not_found`
|
= note: the builtin type `u8` does not have an associated item named `not_found`
|
||||||
|
|
||||||
error: unresolved link to `S`
|
error: unresolved link to `S`
|
||||||
--> $DIR/intra-link-errors.rs:38:6
|
--> $DIR/intra-link-errors.rs:33:6
|
||||||
|
|
|
|
||||||
LL | /// [S!]
|
LL | /// [S!]
|
||||||
| ^^ help: to link to the struct, use its disambiguator: `struct@S`
|
| ^^ help: to link to the struct, use its disambiguator: `struct@S`
|
||||||
|
@ -65,7 +61,7 @@ LL | /// [S!]
|
||||||
= note: this link resolves to the struct `S`, which is not in the macro namespace
|
= note: this link resolves to the struct `S`, which is not in the macro namespace
|
||||||
|
|
||||||
error: unresolved link to `T::g`
|
error: unresolved link to `T::g`
|
||||||
--> $DIR/intra-link-errors.rs:56:6
|
--> $DIR/intra-link-errors.rs:51:6
|
||||||
|
|
|
|
||||||
LL | /// [type@T::g]
|
LL | /// [type@T::g]
|
||||||
| ^^^^^^^^^ help: to link to the associated function, use its disambiguator: `T::g()`
|
| ^^^^^^^^^ help: to link to the associated function, use its disambiguator: `T::g()`
|
||||||
|
@ -73,7 +69,7 @@ LL | /// [type@T::g]
|
||||||
= note: this link resolves to the associated function `g`, which is not in the type namespace
|
= note: this link resolves to the associated function `g`, which is not in the type namespace
|
||||||
|
|
||||||
error: unresolved link to `T::h`
|
error: unresolved link to `T::h`
|
||||||
--> $DIR/intra-link-errors.rs:61:6
|
--> $DIR/intra-link-errors.rs:56:6
|
||||||
|
|
|
|
||||||
LL | /// [T::h!]
|
LL | /// [T::h!]
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
@ -82,7 +78,7 @@ LL | /// [T::h!]
|
||||||
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
|
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
|
||||||
|
|
||||||
error: unresolved link to `S::h`
|
error: unresolved link to `S::h`
|
||||||
--> $DIR/intra-link-errors.rs:48:6
|
--> $DIR/intra-link-errors.rs:43:6
|
||||||
|
|
|
|
||||||
LL | /// [type@S::h]
|
LL | /// [type@S::h]
|
||||||
| ^^^^^^^^^ help: to link to the associated function, use its disambiguator: `S::h()`
|
| ^^^^^^^^^ help: to link to the associated function, use its disambiguator: `S::h()`
|
||||||
|
|
|
@ -5,8 +5,7 @@ LL | //! Test with [Foo::baz], [Bar::foo], ...
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: `#[warn(broken_intra_doc_links)]` on by default
|
= note: `#[warn(broken_intra_doc_links)]` on by default
|
||||||
= note: this link partially resolves to the struct `Foo`
|
= note: the struct `Foo` has no field or associated item named `baz`
|
||||||
= note: no `baz` in `Foo`
|
|
||||||
|
|
||||||
warning: unresolved link to `Bar::foo`
|
warning: unresolved link to `Bar::foo`
|
||||||
--> $DIR/intra-links-warning.rs:3:35
|
--> $DIR/intra-links-warning.rs:3:35
|
||||||
|
|
|
@ -32,7 +32,7 @@ error: unresolved link to `error`
|
||||||
--> $DIR/lint-group.rs:9:29
|
--> $DIR/lint-group.rs:9:29
|
||||||
|
|
|
|
||||||
LL | /// what up, let's make an [error]
|
LL | /// what up, let's make an [error]
|
||||||
| ^^^^^ unresolved link
|
| ^^^^^
|
||||||
|
|
|
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/lint-group.rs:7:9
|
--> $DIR/lint-group.rs:7:9
|
||||||
|
@ -40,6 +40,7 @@ note: the lint level is defined here
|
||||||
LL | #![deny(rustdoc)]
|
LL | #![deny(rustdoc)]
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
= note: `#[deny(broken_intra_doc_links)]` implied by `#[deny(rustdoc)]`
|
= note: `#[deny(broken_intra_doc_links)]` implied by `#[deny(rustdoc)]`
|
||||||
|
= note: no item named `error` is in scope
|
||||||
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
|
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue