]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_save_analysis/lib.rs
save-analysis: handle function types in bounds
[rust.git] / src / librustc_save_analysis / lib.rs
index cf2cad1b38c42c9280c04a3da78526acb130f9ba..9769f3905c7b69aaf977ab8c6899fe7b36ae6b00 100644 (file)
@@ -614,6 +614,19 @@ pub fn get_path_def(&self, id: NodeId) -> HirDef {
     }
 
     pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option<Ref> {
+        // Returns true if the path is function type sugar, e.g., `Fn(A) -> B`.
+        fn fn_type(path: &ast::Path) -> bool {
+            if path.segments.len() != 1 {
+                return false;
+            }
+            if let Some(ref params) = path.segments[0].parameters {
+                if let ast::PathParameters::Parenthesized(_) = **params {
+                    return true;
+                }
+            }
+            false
+        }
+
         let def = self.get_path_def(id);
         let sub_span = self.span_utils.span_for_last_ident(path.span);
         filter!(self.span_utils, sub_span, path.span, None);
@@ -639,6 +652,16 @@ pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option<Ref> {
                     ref_id: id_from_def_id(def.def_id()),
                 })
             }
+            HirDef::Trait(def_id) if fn_type(path) => {
+                // Function type bounds are desugared in the parser, so we have to
+                // special case them here.
+                let fn_span = self.span_utils.span_for_first_ident(path.span);
+                fn_span.map(|span| Ref {
+                    kind: RefKind::Type,
+                    span: self.span_from_span(span),
+                    ref_id: id_from_def_id(def_id),
+                })
+            }
             HirDef::Struct(def_id) |
             HirDef::Variant(def_id, ..) |
             HirDef::Union(def_id) |
@@ -818,29 +841,31 @@ fn make_signature(decl: &ast::FnDecl, generics: &ast::Generics) -> String {
     sig
 }
 
-// An AST visitor for collecting paths from patterns.
-struct PathCollector {
-    // The Row field identifies the kind of pattern.
-    collected_paths: Vec<(NodeId, ast::Path, ast::Mutability)>,
+// An AST visitor for collecting paths (e.g., the names of structs) and formal
+// variables (idents) from patterns.
+struct PathCollector<'l> {
+    collected_paths: Vec<(NodeId, &'l ast::Path)>,
+    collected_idents: Vec<(NodeId, ast::Ident, Span, ast::Mutability)>,
 }
 
-impl PathCollector {
-    fn new() -> PathCollector {
-        PathCollector { collected_paths: vec![] }
+impl<'l> PathCollector<'l> {
+    fn new() -> PathCollector<'l> {
+        PathCollector {
+            collected_paths: vec![],
+            collected_idents: vec![],
+        }
     }
 }
 
-impl<'a> Visitor<'a> for PathCollector {
-    fn visit_pat(&mut self, p: &ast::Pat) {
+impl<'l, 'a: 'l> Visitor<'a> for PathCollector<'l> {
+    fn visit_pat(&mut self, p: &'a ast::Pat) {
         match p.node {
             PatKind::Struct(ref path, ..) => {
-                self.collected_paths.push((p.id, path.clone(),
-                                           ast::Mutability::Mutable));
+                self.collected_paths.push((p.id, path));
             }
             PatKind::TupleStruct(ref path, ..) |
             PatKind::Path(_, ref path) => {
-                self.collected_paths.push((p.id, path.clone(),
-                                           ast::Mutability::Mutable));
+                self.collected_paths.push((p.id, path));
             }
             PatKind::Ident(bm, ref path1, _) => {
                 debug!("PathCollector, visit ident in pat {}: {:?} {:?}",
@@ -854,9 +879,7 @@ fn visit_pat(&mut self, p: &ast::Pat) {
                     ast::BindingMode::ByRef(_) => ast::Mutability::Immutable,
                     ast::BindingMode::ByValue(mt) => mt,
                 };
-                // collect path for either visit_local or visit_arm
-                let path = ast::Path::from_ident(path1.span, path1.node);
-                self.collected_paths.push((p.id, path, immut));
+                self.collected_idents.push((p.id, path1.node, path1.span, immut));
             }
             _ => {}
         }