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, typ: &ast::Ty, impl_items: &[P]) { - 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, + pub self_ref: Option, } /// 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 { + 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 { + 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.