Don't give misleading errors for f::A
, where f is in the value namespace
This commit is contained in:
parent
f4e6ebd11a
commit
002d3a922c
3 changed files with 54 additions and 20 deletions
|
@ -57,6 +57,9 @@ enum ResolutionFailure<'a> {
|
|||
/// This resolved, but with the wrong namespace.
|
||||
/// `Namespace` is the expected namespace (as opposed to the actual).
|
||||
WrongNamespace(Res, Namespace),
|
||||
/// This has a partial resolution, but is not in the TypeNS and so cannot
|
||||
/// have associated items or fields.
|
||||
CannotHaveAssociatedItems(Res, Namespace),
|
||||
/// `String` is the base name of the path (not necessarily the whole link)
|
||||
NotInScope(Cow<'a, str>),
|
||||
/// this is a primitive type without an impls (no associated methods)
|
||||
|
@ -90,7 +93,8 @@ impl ResolutionFailure<'a> {
|
|||
| NoPrimitiveImpl(res, _)
|
||||
| NotAnEnum(res)
|
||||
| NotAVariant(res, _)
|
||||
| WrongNamespace(res, _) => Some(*res),
|
||||
| WrongNamespace(res, _)
|
||||
| CannotHaveAssociatedItems(res, _) => Some(*res),
|
||||
NotInScope(_) | NoParentItem | Dummy => None,
|
||||
}
|
||||
}
|
||||
|
@ -360,21 +364,39 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
|
|||
}));
|
||||
}
|
||||
|
||||
let (_, ty_res) = cx
|
||||
let ty_res = cx
|
||||
.enter_resolver(|resolver| {
|
||||
// only types can have associated items
|
||||
resolver.resolve_str_path_error(DUMMY_SP, &path_root, TypeNS, module_id)
|
||||
})
|
||||
.map_err(|_| {
|
||||
ErrorKind::Resolve(ResolutionFailure::NotInScope(path_root.clone().into()))
|
||||
})?;
|
||||
if let Res::Err = ty_res {
|
||||
return if ns == Namespace::ValueNS {
|
||||
self.variant_field(path_str, current_item, module_id)
|
||||
} else {
|
||||
Err(ErrorKind::Resolve(ResolutionFailure::NotInScope(path_root.into())))
|
||||
};
|
||||
}
|
||||
.map(|(_, res)| res);
|
||||
let ty_res = match ty_res {
|
||||
Err(()) | Ok(Res::Err) => {
|
||||
return if ns == Namespace::ValueNS {
|
||||
self.variant_field(path_str, current_item, module_id)
|
||||
} else {
|
||||
// See if it only broke because of the namespace.
|
||||
let kind = cx.enter_resolver(|resolver| {
|
||||
for &ns in &[MacroNS, ValueNS] {
|
||||
match resolver
|
||||
.resolve_str_path_error(DUMMY_SP, &path_root, ns, module_id)
|
||||
{
|
||||
Ok((_, Res::Err)) | Err(()) => {}
|
||||
Ok((_, res)) => {
|
||||
let res = res.map_id(|_| panic!("unexpected node_id"));
|
||||
return ResolutionFailure::CannotHaveAssociatedItems(
|
||||
res, ns,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
ResolutionFailure::NotInScope(path_root.into())
|
||||
});
|
||||
Err(ErrorKind::Resolve(kind))
|
||||
};
|
||||
}
|
||||
Ok(res) => res,
|
||||
};
|
||||
let ty_res = ty_res.map_id(|_| panic!("unexpected node_id"));
|
||||
let res = match ty_res {
|
||||
Res::Def(
|
||||
|
@ -1006,14 +1028,12 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
|
|||
Ok(res) => (res, extra_fragment),
|
||||
Err(mut kind) => {
|
||||
// `macro_resolve` only looks in the macro namespace. Try to give a better error if possible.
|
||||
//if kind.res().is_none() {
|
||||
for &ns in &[TypeNS, ValueNS] {
|
||||
if let Some(res) = check_full_res(self, ns) {
|
||||
kind = ResolutionFailure::WrongNamespace(res, MacroNS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
//}
|
||||
resolution_failure(
|
||||
cx,
|
||||
&item,
|
||||
|
@ -1456,6 +1476,20 @@ fn resolution_failure(
|
|||
diag.note(¬e);
|
||||
}
|
||||
}
|
||||
ResolutionFailure::CannotHaveAssociatedItems(res, _) => {
|
||||
let (item, _) = item(res);
|
||||
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?
|
||||
ResolutionFailure::NotAnEnum(res) => {
|
||||
let (item, comma) = item(res);
|
||||
|
|
|
@ -7,14 +7,14 @@
|
|||
// FIXME: this could say which path was the first to not be found (in this case, `path`)
|
||||
/// [path::to::nonexistent::module]
|
||||
//~^ ERROR unresolved link
|
||||
//~| NOTE no item named `path::to::nonexistent` is in scope
|
||||
//~| NOTE no item named `path::to` is in scope
|
||||
//~| HELP to escape
|
||||
|
||||
// TODO: why does this say `f` and not `f::A`??
|
||||
/// [f::A]
|
||||
//~^ ERROR unresolved link
|
||||
//~| NOTE no item named `f` is in scope
|
||||
//~| HELP to escape
|
||||
//~| NOTE this link partially resolves
|
||||
//~| NOTE `f` is a function, not a module
|
||||
|
||||
/// [S::A]
|
||||
//~^ ERROR unresolved link
|
||||
|
|
|
@ -9,7 +9,7 @@ note: the lint level is defined here
|
|||
|
|
||||
LL | #![deny(broken_intra_doc_links)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: no item named `path::to::nonexistent` is in scope
|
||||
= note: no item named `path::to` is in scope
|
||||
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
|
||||
|
||||
error: unresolved link to `f::A`
|
||||
|
@ -18,8 +18,8 @@ error: unresolved link to `f::A`
|
|||
LL | /// [f::A]
|
||||
| ^^^^
|
||||
|
|
||||
= note: no item named `f` is in scope
|
||||
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
|
||||
= note: this link partially resolves to the function `f`
|
||||
= note: `f` is a function, not a module or type, and cannot have associated items
|
||||
|
||||
error: unresolved link to `S::A`
|
||||
--> $DIR/intra-link-errors.rs:19:6
|
||||
|
|
Loading…
Add table
Reference in a new issue