about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJoshua Nelson <jyn514@gmail.com>2020-08-21 15:00:30 -0400
committerJoshua Nelson <jyn514@gmail.com>2020-09-05 13:48:19 -0400
commit19d100278d9609c389780e2692dddaeb45fba301 (patch)
tree1bbeef2e0f4c13c85a2c65da58b8d5eb0c5e433e
parente2d69f2eb115b0b6a433977ae7c5a73c249a4f98 (diff)
downloadrust-19d100278d9609c389780e2692dddaeb45fba301.tar.gz
rust-19d100278d9609c389780e2692dddaeb45fba301.zip
Fix failures to resolve primitives
Previously, when looking for the associated items for primitives,
rustdoc would look for primitives in the current namespace.
But all primitives are in the type namespace. To fix this, rustdoc now
always looks for primitives in the namespace when considering them as a
stepping stone to the associated item.

However, fixing that bug caused several duplicate errors because rustdoc
now reports the same error in each namespace. To avoid this, rustdoc now
ignores all duplicate errors when issuing them.
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs20
1 files changed, 15 insertions, 5 deletions
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index c69850f9d97..9a88c8eb42a 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -331,7 +331,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
                     ErrorKind::Resolve(ResolutionFailure::NotInScope(item_name.to_string().into()))
                 })?;
 
-            if let Some((path, prim)) = is_primitive(&path_root, ns) {
+            if let Some((path, prim)) = is_primitive(&path_root, TypeNS) {
                 let impls = primitive_impl(cx, &path).ok_or_else(|| {
                     ErrorKind::Resolve(ResolutionFailure::NoPrimitiveImpl(prim, path_root.into()))
                 })?;
@@ -355,6 +355,12 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
                         return Ok(link);
                     }
                 }
+                debug!(
+                    "returning primitive error for {}::{} in {} namespace",
+                    path,
+                    item_name,
+                    ns.descr()
+                );
                 return Err(ErrorKind::Resolve(ResolutionFailure::NoPrimitiveAssocItem {
                     res: prim,
                     prim_name: path,
@@ -1404,7 +1410,6 @@ fn resolution_failure(
         &link_range,
         |diag, sp| {
             let in_scope = kinds.iter().any(|kind| kind.res().is_some());
-            let mut reported_not_in_scope = false;
             let item = |res: Res| {
                 format!("the {} `{}`", res.descr(), cx.tcx.item_name(res.def_id()).to_string())
             };
@@ -1419,14 +1424,19 @@ fn resolution_failure(
                 );
                 diag.note(&note);
             };
+            // ignore duplicates
+            let mut variants_seen = SmallVec::<[_; 3]>::new();
             for failure in kinds {
+                let variant = std::mem::discriminant(&failure);
+                if variants_seen.contains(&variant) {
+                    continue;
+                }
+                variants_seen.push(variant);
                 match failure {
-                    // already handled above
                     ResolutionFailure::NotInScope(base) => {
-                        if in_scope || reported_not_in_scope {
+                        if in_scope {
                             continue;
                         }
-                        reported_not_in_scope = true;
                         diag.note(&format!("no item named `{}` is in scope", base));
                         diag.help(r#"to escape `[` and `]` characters, add '\' before them like `\[` or `\]`"#);
                     }