about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorNick Cameron <ncameron@mozilla.com>2015-06-05 17:50:04 +1200
committerNick Cameron <ncameron@mozilla.com>2015-06-15 08:15:29 +1200
commit78c25eabd588a81ce48d6b81f00dbb18ff1c3418 (patch)
treeeeb1552aa60aed273df7eec3432dbec04a3e391f /src
parentabe5f7b95a1d856b69eb68344426e29d30918aea (diff)
save-analysis: API-ify impls
Diffstat (limited to 'src')
-rw-r--r--src/librustc_trans/save/dump_csv.rs97
-rw-r--r--src/librustc_trans/save/mod.rs87
2 files changed, 131 insertions, 53 deletions
diff --git a/src/librustc_trans/save/dump_csv.rs b/src/librustc_trans/save/dump_csv.rs
index 6f6d02e95a4..f61748afbc5 100644
--- a/src/librustc_trans/save/dump_csv.rs
+++ b/src/librustc_trans/save/dump_csv.rs
@@ -419,19 +419,15 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
                                     id);
     }
 
-    fn process_trait_ref(&mut self,
-                         trait_ref: &ast::TraitRef) {
-        match self.lookup_type_ref(trait_ref.ref_id) {
-            Some(id) => {
-                let sub_span = self.span.sub_span_for_type_name(trait_ref.path.span);
-                self.fmt.ref_str(recorder::TypeRef,
-                                 trait_ref.path.span,
-                                 sub_span,
-                                 id,
-                                 self.cur_scope);
-                visit::walk_path(self, &trait_ref.path);
-            },
-            None => ()
+    fn process_trait_ref(&mut self, trait_ref: &ast::TraitRef) {
+        let trait_ref_data = self.save_ctxt.get_trait_ref_data(trait_ref, self.cur_scope);
+        if let Some(trait_ref_data) = trait_ref_data {
+            self.fmt.ref_str(recorder::TypeRef,
+                             trait_ref.path.span,
+                             Some(trait_ref_data.span),
+                             trait_ref_data.ref_id,
+                             trait_ref_data.scope);
+            visit::walk_path(self, &trait_ref.path);
         }
     }
 
@@ -600,8 +596,9 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
                               Some(enum_data.span),
                               enum_data.id,
                               &enum_data.qualname,
-                              self.cur_scope,
+                              enum_data.scope,
                               &enum_data.value);
+
             for variant in &enum_definition.variants {
                 let name = &get_ident(variant.node.name);
                 let mut qualname = enum_data.qualname.clone();
@@ -618,7 +615,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
                                                    &qualname,
                                                    &enum_data.qualname,
                                                    &val,
-                                                   item.id);
+                                                   enum_data.id);
                         for arg in args {
                             self.visit_ty(&*arg.ty);
                         }
@@ -635,7 +632,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
                                                     &qualname,
                                                     &enum_data.qualname,
                                                     &val,
-                                                    item.id);
+                                                    enum_data.id);
 
                         for field in &struct_def.fields {
                             self.process_struct_field_def(field, variant.node.id);
@@ -644,7 +641,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
                     }
                 }
             }
-            self.process_generic_params(ty_params, item.span, &enum_data.qualname, item.id);
+            self.process_generic_params(ty_params, item.span, &enum_data.qualname, enum_data.id);
         } else {
             self.sess.span_bug(item.span, "expected EnumData");
         }
@@ -656,43 +653,37 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
                     trait_ref: &Option<ast::TraitRef>,
                     typ: &ast::Ty,
                     impl_items: &[P<ast::ImplItem>]) {
-        let trait_id = trait_ref.as_ref().and_then(|tr| self.lookup_type_ref(tr.ref_id));
-        match typ.node {
-            // Common case impl for a struct or something basic.
-            ast::TyPath(None, ref path) => {
-                let sub_span = self.span.sub_span_for_type_name(path.span);
-                let self_id = self.lookup_type_ref(typ.id).map(|id| {
+        let impl_data = self.save_ctxt.get_item_data(item);
+        if let super::Data::ImplData(impl_data) = impl_data {
+            match impl_data.self_ref {
+                Some(ref self_ref) => {
                     self.fmt.ref_str(recorder::TypeRef,
-                                     path.span,
-                                     sub_span,
-                                     id,
-                                     self.cur_scope);
-                    id
-                });
-                self.fmt.impl_str(path.span,
-                                  sub_span,
-                                  item.id,
-                                  self_id,
-                                  trait_id,
-                                  self.cur_scope);
-            },
-            _ => {
-                // Less useful case, impl for a compound type.
-                self.visit_ty(&*typ);
-
-                let sub_span = self.span.sub_span_for_type_name(typ.span);
-                self.fmt.impl_str(typ.span,
-                                  sub_span,
-                                  item.id,
-                                  None,
-                                  trait_id,
-                                  self.cur_scope);
+                                     item.span,
+                                     Some(self_ref.span),
+                                     self_ref.ref_id,
+                                     self_ref.scope);
+                }
+                None => {
+                    self.visit_ty(&typ);
+                }
+            }
+            if let Some(ref trait_ref_data) = impl_data.trait_ref {
+                self.fmt.ref_str(recorder::TypeRef,
+                                 item.span,
+                                 Some(trait_ref_data.span),
+                                 trait_ref_data.ref_id,
+                                 trait_ref_data.scope);
+                visit::walk_path(self, &trait_ref.as_ref().unwrap().path);
             }
-        }
 
-        match *trait_ref {
-            Some(ref trait_ref) => self.process_trait_ref(trait_ref),
-            None => (),
+            self.fmt.impl_str(item.span,
+                              Some(impl_data.span),
+                              impl_data.id,
+                              impl_data.self_ref.map(|data| data.ref_id),
+                              impl_data.trait_ref.map(|data| data.ref_id),
+                              impl_data.scope);
+        } else {
+            self.sess.span_bug(item.span, "expected ImplData");
         }
 
         self.process_generic_params(type_parameters, item.span, "", item.id);
@@ -717,7 +708,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
                            &val);
 
         // super-traits
-        for super_bound in trait_refs.iter() {
+        for super_bound in &trait_refs {
             let trait_ref = match *super_bound {
                 ast::TraitTyParamBound(ref trait_ref, _) => {
                     trait_ref
@@ -1164,7 +1155,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
                 self.process_impl(item,
                                   ty_params,
                                   trait_ref,
-                                  &**typ,
+                                  &typ,
                                   impl_items)
             }
             ast::ItemTrait(_, ref generics, ref trait_refs, ref methods) =>
diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs
index 6d3de80ab14..76decc02a54 100644
--- a/src/librustc_trans/save/mod.rs
+++ b/src/librustc_trans/save/mod.rs
@@ -10,6 +10,7 @@
 
 use session::Session;
 use middle::ty;
+use middle::def;
 
 use std::env;
 use std::fs::{self, File};
@@ -55,10 +56,14 @@ pub enum Data {
     ModData(ModData),
     /// Data for Enums.
     EnumData(EnumData),
+    /// Data for impls.
+    ImplData(ImplData),
 
     /// Data for the use of some variable (e.g., the use of a local variable, which
     /// will refere to that variables declaration).
     VariableRefData(VariableRefData),
+    /// Data for a reference to a type or trait.
+    TypeRefData(TypeRefData),
 }
 
 /// Data for all kinds of functions and methods.
@@ -98,6 +103,18 @@ pub struct EnumData {
     pub value: String,
     pub qualname: String,
     pub span: Span,
+    pub scope: NodeId,
+}
+
+pub struct ImplData {
+    pub id: NodeId,
+    pub span: Span,
+    pub scope: NodeId,
+    // FIXME: I'm not really sure inline data is the best way to do this. Seems
+    // OK in this case, but generalising leads to returning chunks of AST, which
+    // feels wrong.
+    pub trait_ref: Option<TypeRefData>,
+    pub self_ref: Option<TypeRefData>,
 }
 
 /// Data for the use of some item (e.g., the use of a local variable, which
@@ -109,6 +126,13 @@ pub struct VariableRefData {
     pub ref_id: DefId,
 }
 
+/// Data for a reference to a type or trait.
+pub struct TypeRefData {
+    pub span: Span,
+    pub scope: NodeId,
+    pub ref_id: DefId,
+}
+
 
 impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
     pub fn new(sess: &'l Session,
@@ -211,8 +235,42 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                     value: val,
                     span: sub_span.unwrap(),
                     qualname: enum_name,
+                    scope: self.analysis.ty_cx.map.get_parent(item.id),
                 })
             },
+            ast::ItemImpl(_, _, _, ref trait_ref, ref typ, _) => {
+                let mut type_data = None;
+                let sub_span;
+
+                let parent = self.analysis.ty_cx.map.get_parent(item.id);
+
+                match typ.node {
+                    // Common case impl for a struct or something basic.
+                    ast::TyPath(None, ref path) => {
+                        sub_span = self.span_utils.sub_span_for_type_name(path.span);
+                        type_data = self.lookup_ref_id(typ.id).map(|id| TypeRefData {
+                            span: sub_span.unwrap(),
+                            scope: parent,
+                            ref_id: id,
+                        });
+                    },
+                    _ => {
+                        // Less useful case, impl for a compound type.
+                        sub_span = self.span_utils.sub_span_for_type_name(typ.span);
+                    }
+                }
+
+                let trait_data =
+                    trait_ref.as_ref().and_then(|tr| self.get_trait_ref_data(tr, parent));
+
+                Data::ImplData(ImplData {
+                    id: item.id,
+                    span: sub_span.unwrap(),
+                    scope: parent,
+                    trait_ref: trait_data,
+                    self_ref: type_data,
+                })
+            }
             _ => {
                 // FIXME
                 unimplemented!();
@@ -247,6 +305,22 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
         }
     }
 
+    // FIXME: we ought to be able to get the parent id ourselves, but we can't
+    // for now.
+    pub fn get_trait_ref_data(&self,
+                              trait_ref: &ast::TraitRef,
+                              parent: NodeId)
+                              -> Option<TypeRefData> {
+        self.lookup_ref_id(trait_ref.ref_id).map(|def_id| {
+            let sub_span = self.span_utils.sub_span_for_type_name(trait_ref.path.span);
+            TypeRefData {
+                span: sub_span.unwrap(),
+                scope: parent,
+                ref_id: def_id,
+            }
+        })
+    }
+
     pub fn get_expr_data(&self, expr: &ast::Expr) -> Data {
         match expr.node {
             ast::ExprField(ref sub_ex, ident) => {
@@ -286,6 +360,19 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
         // FIXME
         unimplemented!();
     }
+
+    fn lookup_ref_id(&self, ref_id: NodeId) -> Option<DefId> {
+        if !self.analysis.ty_cx.def_map.borrow().contains_key(&ref_id) {
+            self.sess.bug(&format!("def_map has no key for {} in lookup_type_ref",
+                                  ref_id));
+        }
+        let def = self.analysis.ty_cx.def_map.borrow().get(&ref_id).unwrap().full_def();
+        match def {
+            def::DefPrimTy(_) => None,
+            _ => Some(def.def_id()),
+        }
+    }
+
 }
 
 // An AST visitor for collecting paths from patterns.