]> git.lizzy.rs Git - rust.git/commitdiff
Make resolve_hir_path and resolve_str_path fallible
authorManish Goregaokar <manishsmail@gmail.com>
Fri, 29 Dec 2017 08:06:32 +0000 (13:36 +0530)
committerManish Goregaokar <manishsmail@gmail.com>
Mon, 22 Jan 2018 09:54:28 +0000 (15:24 +0530)
src/librustc/hir/lowering.rs
src/librustc_resolve/lib.rs

index f2154f885fa4a22fa05f0493bb422a54ff57cf36..a87f2747a57f513f57391851c5a09411287cb32c 100644 (file)
@@ -155,18 +155,7 @@ pub trait Resolver {
     /// Given suffix ["b","c","d"], creates a HIR path for `[::crate_root]::b::c::d` and resolves
     /// it based on `is_value`.
     fn resolve_str_path(&mut self, span: Span, crate_root: Option<&str>,
-                components: &[&str], is_value: bool) -> hir::Path {
-        let mut path = hir::Path {
-            span,
-            def: Def::Err,
-            segments: iter::once(keywords::CrateRoot.name()).chain({
-                crate_root.into_iter().chain(components.iter().cloned()).map(Symbol::intern)
-            }).map(hir::PathSegment::from_name).collect(),
-        };
-
-        self.resolve_hir_path(&mut path, is_value);
-        path
-    }
+                components: &[&str], is_value: bool) -> hir::Path;
 }
 
 #[derive(Clone, Copy, Debug)]
index d9ae776a4d7b26a9b499578b8714813a50edbe25..fdbed251799874a07592c9b2a6f6024eb9a9da67 100644 (file)
@@ -1407,6 +1407,64 @@ fn parent(self, id: DefId) -> Option<DefId> {
 
 impl<'a> hir::lowering::Resolver for Resolver<'a> {
     fn resolve_hir_path(&mut self, path: &mut hir::Path, is_value: bool) {
+        self.resolve_hir_path_cb(path, is_value,
+                                 |resolver, span, error| resolve_error(resolver, span, error))
+    }
+
+    fn resolve_str_path(&mut self, span: Span, crate_root: Option<&str>,
+                components: &[&str], is_value: bool) -> hir::Path {
+        self.resolve_str_path_cb(span, crate_root, components, is_value,
+                                 |resolver, span, error| resolve_error(resolver, span, error))
+    }
+
+    fn get_resolution(&mut self, id: NodeId) -> Option<PathResolution> {
+        self.def_map.get(&id).cloned()
+    }
+
+    fn definitions(&mut self) -> &mut Definitions {
+        &mut self.definitions
+    }
+}
+
+impl<'a> Resolver<'a> {
+    /// resolve_str_path, but takes a callback in case there was an error
+    fn resolve_str_path_cb<F>(&mut self, span: Span, crate_root: Option<&str>,
+                components: &[&str], is_value: bool, error_callback: F) -> hir::Path 
+            where F: for<'b, 'c> FnOnce(&'c mut Resolver, Span, ResolutionError<'b>)
+        {
+        use std::iter;
+        let mut path = hir::Path {
+            span,
+            def: Def::Err,
+            segments: iter::once(keywords::CrateRoot.name()).chain({
+                crate_root.into_iter().chain(components.iter().cloned()).map(Symbol::intern)
+            }).map(hir::PathSegment::from_name).collect(),
+        };
+
+        self.resolve_hir_path_cb(&mut path, is_value, error_callback);
+        path
+    }
+
+    /// Rustdoc uses this to resolve things in a recoverable way. ResolutionError<'a>
+    /// isn't something that can be returned because it can't be made to live that long,
+    /// and also it's a private type. Fortunately rustdoc doesn't need to know the error,
+    /// just that an error occured.
+    pub fn resolve_str_path_error(&mut self, span: Span, crate_root: Option<&str>,
+                components: &[&str], is_value: bool) -> Result<hir::Path, ()> {
+        let mut errored = false;
+        let path = self.resolve_str_path_cb(span, crate_root, components, is_value,
+                                            |_, _, _| errored = true);
+        if errored || path.def == Def::Err {
+            Err(())
+        } else {
+            Ok(path)
+        }
+    }
+
+    /// resolve_hir_path, but takes a callback in case there was an error
+    fn resolve_hir_path_cb<F>(&mut self, path: &mut hir::Path, is_value: bool, error_callback: F)
+            where F: for<'c, 'b> FnOnce(&'c mut Resolver, Span, ResolutionError<'b>)
+        {
         let namespace = if is_value { ValueNS } else { TypeNS };
         let hir::Path { ref segments, span, ref mut def } = *path;
         let path: Vec<SpannedIdent> = segments.iter()
@@ -1418,24 +1476,16 @@ fn resolve_hir_path(&mut self, path: &mut hir::Path, is_value: bool) {
                 *def = path_res.base_def(),
             PathResult::NonModule(..) => match self.resolve_path(&path, None, true, span) {
                 PathResult::Failed(span, msg, _) => {
-                    resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
+                    error_callback(self, span, ResolutionError::FailedToResolve(&msg));
                 }
                 _ => {}
             },
             PathResult::Indeterminate => unreachable!(),
             PathResult::Failed(span, msg, _) => {
-                resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
+                error_callback(self, span, ResolutionError::FailedToResolve(&msg));
             }
         }
     }
-
-    fn get_resolution(&mut self, id: NodeId) -> Option<PathResolution> {
-        self.def_map.get(&id).cloned()
-    }
-
-    fn definitions(&mut self) -> &mut Definitions {
-        &mut self.definitions
-    }
 }
 
 impl<'a> Resolver<'a> {