diff options
| author | Joshua Nelson <jyn514@gmail.com> | 2020-08-28 01:31:33 -0400 |
|---|---|---|
| committer | Joshua Nelson <jyn514@gmail.com> | 2020-09-05 13:56:57 -0400 |
| commit | efdc3facdfe931108146587b2f9d22b7dfd217c5 (patch) | |
| tree | a54e0fbd163b40a8188b336746030ba8c95dbcf8 /src | |
| parent | ee683ef8532034a4bee01e9aa8fd92dbe38ac6f1 (diff) | |
| download | rust-efdc3facdfe931108146587b2f9d22b7dfd217c5.tar.gz rust-efdc3facdfe931108146587b2f9d22b7dfd217c5.zip | |
Give a much better error message when an item has a macro disambiguator
Previously, this called `check_full_res` for values and types, but not macros. This would result in not showing when there was a partial resolution for a parent of the item. This now calls `check_full_res`. Additionally, it checks if there was a disambiguator, and if so, says that specific kind wasn't found instead of saying generically 'associated item'.
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustdoc/passes/collect_intra_doc_links.rs | 87 | ||||
| -rw-r--r-- | src/test/rustdoc-ui/intra-link-errors.rs | 2 | ||||
| -rw-r--r-- | src/test/rustdoc-ui/intra-link-errors.stderr | 2 |
3 files changed, 59 insertions, 32 deletions
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index a19387ad992..df8ecf26a41 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -262,11 +262,11 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { false, ) { if let SyntaxExtensionKind::LegacyBang { .. } = ext.kind { - return Ok(res.map_id(|_| panic!("unexpected id"))); + return Some(Ok(res.map_id(|_| panic!("unexpected id")))); } } if let Some(res) = resolver.all_macros().get(&Symbol::intern(path_str)) { - return Ok(res.map_id(|_| panic!("unexpected id"))); + return Some(Ok(res.map_id(|_| panic!("unexpected id")))); } if let Some(module_id) = parent_id { debug!("resolving {} as a macro in the module {:?}", path_str, module_id); @@ -276,14 +276,32 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { // don't resolve builtins like `#[derive]` if let Res::Def(..) = res { let res = res.map_id(|_| panic!("unexpected node_id")); - return Ok(res); + return Some(Ok(res)); } } } else { debug!("attempting to resolve item without parent module: {}", path_str); - return Err(ResolutionFailure::NoParentItem); + return Some(Err(ResolutionFailure::NoParentItem)); } - return Err(ResolutionFailure::NotInScope(path_str.into())); + None + }) + // This weird control flow is so we don't borrow the resolver more than once at a time + .unwrap_or_else(|| { + let mut split = path_str.rsplitn(2, "::"); + if let Some((parent, base)) = split.next().and_then(|x| Some((split.next()?, x))) { + if let Some(res) = self.check_full_res(TypeNS, parent, parent_id, &None, &None) { + return Err(if matches!(res, Res::PrimTy(_)) { + ResolutionFailure::NoPrimitiveAssocItem { + res, + prim_name: parent, + assoc_item: Symbol::intern(base), + } + } else { + ResolutionFailure::NoAssocItem(res, Symbol::intern(base)) + }); + } + } + Err(ResolutionFailure::NotInScope(path_str.into())) }) } /// Resolves a string as a path within a particular namespace. Also returns an optional @@ -981,6 +999,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { cx, &item, path_str, + disambiguator, &dox, link_range, smallvec![kind], @@ -1060,6 +1079,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { cx, &item, path_str, + disambiguator, &dox, link_range, candidates.into_iter().filter_map(|res| res.err()).collect(), @@ -1114,6 +1134,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { cx, &item, path_str, + disambiguator, &dox, link_range, smallvec![kind], @@ -1489,6 +1510,7 @@ fn resolution_failure( cx: &DocContext<'_>, item: &Item, path_str: &str, + disambiguator: Option<Disambiguator>, dox: &str, link_range: Option<Range<usize>>, kinds: SmallVec<[ResolutionFailure<'_>; 3]>, @@ -1581,34 +1603,39 @@ fn resolution_failure( let (kind, def_id) = match res { Res::Def(kind, def_id) => (kind, def_id), - _ => unreachable!( - "primitives are covered above and other `Res` variants aren't possible at module scope" + x => unreachable!( + "primitives are covered above and other `Res` variants aren't possible at module scope: {:?}", + x, ), }; 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 path_description = if let Some(disambiguator) = disambiguator { + disambiguator.descr() + } else { + 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 `{}`", diff --git a/src/test/rustdoc-ui/intra-link-errors.rs b/src/test/rustdoc-ui/intra-link-errors.rs index 919c46fe1da..ae89f418984 100644 --- a/src/test/rustdoc-ui/intra-link-errors.rs +++ b/src/test/rustdoc-ui/intra-link-errors.rs @@ -65,7 +65,7 @@ impl S { /// [T::h!] //~^ ERROR unresolved link -//~| NOTE no item named `T::h` +//~| NOTE `T` has no macro named `h` pub trait T { fn g() {} } diff --git a/src/test/rustdoc-ui/intra-link-errors.stderr b/src/test/rustdoc-ui/intra-link-errors.stderr index 7318193964f..68941d64c7a 100644 --- a/src/test/rustdoc-ui/intra-link-errors.stderr +++ b/src/test/rustdoc-ui/intra-link-errors.stderr @@ -97,7 +97,7 @@ error: unresolved link to `T::h` LL | /// [T::h!] | ^^^^^ | - = note: no item named `T::h` is in scope + = note: the trait `T` has no macro named `h` error: unresolved link to `S::h` --> $DIR/intra-link-errors.rs:54:6 |
