]> git.lizzy.rs Git - rust.git/commitdiff
Report if the thing exists in another namespace
authorJoshua Nelson <jyn514@gmail.com>
Fri, 21 Aug 2020 02:31:44 +0000 (22:31 -0400)
committerJoshua Nelson <jyn514@gmail.com>
Sat, 5 Sep 2020 17:48:19 +0000 (13:48 -0400)
src/librustdoc/passes/collect_intra_doc_links.rs
src/test/rustdoc-ui/intra-link-errors.rs

index 9bf30c71892aa94c1a9ad26164d883ddf830abdf..50132577367196617bad3927040d68228a347897 100644 (file)
@@ -81,6 +81,7 @@ enum ResolutionFailure<'a> {
 }
 
 impl ResolutionFailure<'a> {
 }
 
 impl ResolutionFailure<'a> {
+    // A partial or full resolution
     fn res(&self) -> Option<Res> {
         use ResolutionFailure::*;
         match self {
     fn res(&self) -> Option<Res> {
         use ResolutionFailure::*;
         match self {
@@ -93,6 +94,14 @@ fn res(&self) -> Option<Res> {
             NotInScope(_) | NoParentItem | Dummy => None,
         }
     }
             NotInScope(_) | NoParentItem | Dummy => None,
         }
     }
+
+    // This resolved fully (not just partially) but is erroneous for some other reason
+    fn full_res(&self) -> Option<Res> {
+        match self {
+            Self::WrongNamespace(res, _) => Some(*res),
+            _ => None,
+        }
+    }
 }
 
 enum AnchorFailure {
 }
 
 enum AnchorFailure {
@@ -128,6 +137,7 @@ fn variant_field(
     ) -> Result<(Res, Option<String>), ErrorKind<'path>> {
         let cx = self.cx;
 
     ) -> Result<(Res, Option<String>), ErrorKind<'path>> {
         let cx = self.cx;
 
+        debug!("looking for enum variant {}", path_str);
         let mut split = path_str.rsplitn(3, "::");
         let variant_field_name = split
             .next()
         let mut split = path_str.rsplitn(3, "::");
         let variant_field_name = split
             .next()
@@ -260,7 +270,7 @@ fn resolve<'path>(
             debug!("{} resolved to {:?} in namespace {:?}", path_str, result, ns);
             let result = match result {
                 Ok((_, Res::Err)) => Err(()),
             debug!("{} resolved to {:?} in namespace {:?}", path_str, result, ns);
             let result = match result {
                 Ok((_, Res::Err)) => Err(()),
-                _ => result.map_err(|_| ()),
+                x => x,
             };
 
             if let Ok((_, res)) = result {
             };
 
             if let Ok((_, res)) = result {
@@ -419,6 +429,7 @@ fn resolve<'path>(
                             Ok((ty_res, Some(format!("{}.{}", out, item_name))))
                         })
                     } else if ns == Namespace::ValueNS {
                             Ok((ty_res, Some(format!("{}.{}", out, item_name))))
                         })
                     } else if ns == Namespace::ValueNS {
+                        debug!("looking for variants or fields named {} for {:?}", item_name, did);
                         match cx.tcx.type_of(did).kind() {
                             ty::Adt(def, _) => {
                                 let field = if def.is_enum() {
                         match cx.tcx.type_of(did).kind() {
                             ty::Adt(def, _) => {
                                 let field = if def.is_enum() {
@@ -838,12 +849,36 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
                     }
                 }
 
                     }
                 }
 
+                // used for reporting better errors
+                let check_full_res = |this: &mut Self, ns| {
+                    match this.resolve(path_str, ns, &current_item, base_node, &extra_fragment) {
+                        Ok(res) => {
+                            debug!(
+                                "check_full_res: saw res for {} in {:?} ns: {:?}",
+                                path_str, ns, res.0
+                            );
+                            Some(res.0)
+                        }
+                        Err(ErrorKind::Resolve(kind)) => kind.full_res(),
+                        // TODO: add `Res` to AnchorFailure
+                        Err(ErrorKind::AnchorFailure(_)) => None,
+                    }
+                };
+
                 match disambiguator.map(Disambiguator::ns) {
                     Some(ns @ (ValueNS | TypeNS)) => {
                         match self.resolve(path_str, ns, &current_item, base_node, &extra_fragment)
                         {
                             Ok(res) => res,
                 match disambiguator.map(Disambiguator::ns) {
                     Some(ns @ (ValueNS | TypeNS)) => {
                         match self.resolve(path_str, ns, &current_item, base_node, &extra_fragment)
                         {
                             Ok(res) => res,
-                            Err(ErrorKind::Resolve(kind)) => {
+                            Err(ErrorKind::Resolve(mut kind)) => {
+                                // We only looked in one namespace. Try to give a better error if possible.
+                                // TODO: handle MacroNS too
+                                if kind.full_res().is_none() {
+                                    let other_ns = if ns == ValueNS { TypeNS } else { ValueNS };
+                                    if let Some(res) = check_full_res(self, other_ns) {
+                                        kind = ResolutionFailure::WrongNamespace(res, other_ns);
+                                    }
+                                }
                                 resolution_failure(
                                     cx,
                                     &item,
                                 resolution_failure(
                                     cx,
                                     &item,
@@ -965,30 +1000,14 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
                             Ok(res) => (res, extra_fragment),
                             Err(mut kind) => {
                                 // `macro_resolve` only looks in the macro namespace. Try to give a better error if possible.
                             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] {
                                 for &ns in &[TypeNS, ValueNS] {
-                                    match self.resolve(
-                                        path_str,
-                                        ns,
-                                        &current_item,
-                                        base_node,
-                                        &extra_fragment,
-                                    ) {
-                                        Ok(res) => {
-                                            kind = ResolutionFailure::WrongNamespace(res.0, MacroNS)
-                                        }
-                                        // This will show up in the other namespace, no need to handle it here
-                                        Err(ErrorKind::Resolve(
-                                            ResolutionFailure::WrongNamespace(..),
-                                        )) => {}
-                                        Err(ErrorKind::AnchorFailure(_)) => {}
-                                        Err(ErrorKind::Resolve(inner_kind)) => {
-                                            if let Some(res) = inner_kind.res() {
-                                                kind =
-                                                    ResolutionFailure::WrongNamespace(res, MacroNS);
-                                            }
-                                        }
+                                    if let Some(res) = check_full_res(self, ns) {
+                                        kind = ResolutionFailure::WrongNamespace(res, MacroNS);
+                                        break;
                                     }
                                 }
                                     }
                                 }
+                                //}
                                 resolution_failure(
                                     cx,
                                     &item,
                                 resolution_failure(
                                     cx,
                                     &item,
index 7a53a6f079334ad6f148de9fb3280e1b36d741f8..99d080fb324e319a9cb72ba2bc0df3ec0c1d4613 100644 (file)
@@ -54,6 +54,7 @@ pub fn h() {}
 }
 
 /// [type@T::g]
 }
 
 /// [type@T::g]
+/// [T::h!]
 pub trait T {
     fn g() {}
 }
 pub trait T {
     fn g() {}
 }