about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_save_analysis/dump_visitor.rs169
-rw-r--r--src/librustc_save_analysis/lib.rs116
-rw-r--r--src/librustc_save_analysis/span_utils.rs184
3 files changed, 124 insertions, 345 deletions
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index 97bdb9e5fa3..d05f37cc0a1 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -34,7 +34,6 @@ use std::env;
 
 use syntax::ast::{self, Attribute, NodeId, PatKind, CRATE_NODE_ID};
 use syntax::parse::token;
-use syntax::symbol::keywords;
 use syntax::visit::{self, Visitor};
 use syntax::print::pprust::{
     bounds_to_string,
@@ -323,7 +322,6 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
             self.visit_pat(&arg.pat);
             let mut collector = PathCollector::new();
             collector.visit_pat(&arg.pat);
-            let span_utils = self.span.clone();
 
             for (id, ident, ..) in collector.collected_idents {
                 let hir_id = self.tcx.hir.node_to_hir_id(id);
@@ -331,10 +329,9 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
                     Some(s) => s.to_string(),
                     None => continue,
                 };
-                let sub_span = span_utils.span_for_last_ident(ident.span);
-                if !self.span.filter_generated(sub_span, ident.span) {
+                if !self.span.filter_generated(ident.span) {
                     let id = ::id_from_node_id(id, &self.save_ctxt);
-                    let span = self.span_from_span(sub_span.expect("No span found for variable"));
+                    let span = self.span_from_span(ident.span);
 
                     self.dumper.dump_def(
                         &Access {
@@ -373,7 +370,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
     ) {
         debug!("process_method: {}:{}", id, ident);
 
-        if let Some(mut method_data) = self.save_ctxt.get_method_data(id, ident.name, span) {
+        if let Some(mut method_data) = self.save_ctxt.get_method_data(id, ident, span) {
             let sig_str = ::make_signature(&sig.decl, &generics);
             if body.is_some() {
                 self.nest_tables(
@@ -382,7 +379,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
                 );
             }
 
-            self.process_generic_params(&generics, span, &method_data.qualname, id);
+            self.process_generic_params(&generics, &method_data.qualname, id);
 
             method_data.value = sig_str;
             method_data.sig = sig::method_signature(id, ident, generics, sig, &self.save_ctxt);
@@ -415,7 +412,6 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
     fn process_generic_params(
         &mut self,
         generics: &'l ast::Generics,
-        full_span: Span,
         prefix: &str,
         id: NodeId,
     ) {
@@ -427,7 +423,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
                     let name = escape(self.span.snippet(param_ss));
                     // Append $id to name to make sure each one is unique.
                     let qualname = format!("{}::{}${}", prefix, name, id);
-                    if !self.span.filter_generated(Some(param_ss), full_span) {
+                    if !self.span.filter_generated(param_ss) {
                         let id = ::id_from_node_id(param.id, &self.save_ctxt);
                         let span = self.span_from_span(param_ss);
 
@@ -471,7 +467,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
                 item.id,
                 |v| v.process_formals(&decl.inputs, &fn_data.qualname),
             );
-            self.process_generic_params(ty_params, item.span, &fn_data.qualname, item.id);
+            self.process_generic_params(ty_params, &fn_data.qualname, item.id);
             self.dumper.dump_def(&access_from!(self.save_ctxt, item), fn_data);
         }
 
@@ -505,8 +501,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
     fn process_assoc_const(
         &mut self,
         id: ast::NodeId,
-        name: ast::Name,
-        span: Span,
+        ident: ast::Ident,
         typ: &'l ast::Ty,
         expr: Option<&'l ast::Expr>,
         parent_id: DefId,
@@ -515,11 +510,9 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
     ) {
         let qualname = format!("::{}", self.tcx.node_path_str(id));
 
-        let sub_span = self.span.sub_span_after_keyword(span, keywords::Const);
-
-        if !self.span.filter_generated(sub_span, span) {
-            let sig = sig::assoc_const_signature(id, name, typ, expr, &self.save_ctxt);
-            let span = self.span_from_span(sub_span.expect("No span found for variable"));
+        if !self.span.filter_generated(ident.span) {
+            let sig = sig::assoc_const_signature(id, ident.name, typ, expr, &self.save_ctxt);
+            let span = self.span_from_span(ident.span);
 
             self.dumper.dump_def(
                 &access_from!(self.save_ctxt, vis, id),
@@ -527,7 +520,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
                     kind: DefKind::Const,
                     id: ::id_from_node_id(id, &self.save_ctxt),
                     span,
-                    name: name.to_string(),
+                    name: ident.name.to_string(),
                     qualname,
                     value: ty_to_string(&typ),
                     parent: Some(::id_from_def_id(parent_id)),
@@ -558,13 +551,12 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
         let name = item.ident.to_string();
         let qualname = format!("::{}", self.tcx.node_path_str(item.id));
 
-        let (kind, keyword) = match item.node {
-            ast::ItemKind::Struct(_, _) => (DefKind::Struct, keywords::Struct),
-            ast::ItemKind::Union(_, _) => (DefKind::Union, keywords::Union),
+        let kind = match item.node {
+            ast::ItemKind::Struct(_, _) => DefKind::Struct,
+            ast::ItemKind::Union(_, _) => DefKind::Union,
             _ => unreachable!(),
         };
 
-        let sub_span = self.span.sub_span_after_keyword(item.span, keyword);
         let (value, fields) = match item.node {
             ast::ItemKind::Struct(ast::VariantData::Struct(ref fields, _), _) |
             ast::ItemKind::Union(ast::VariantData::Struct(ref fields, _), _) => {
@@ -595,8 +587,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
             _ => (String::new(), vec![]),
         };
 
-        if !self.span.filter_generated(sub_span, item.span) {
-            let span = self.span_from_span(sub_span.expect("No span found for struct"));
+        if !self.span.filter_generated(item.ident.span) {
+            let span = self.span_from_span(item.ident.span);
             self.dumper.dump_def(
                 &access_from!(self.save_ctxt, item),
                 Def {
@@ -621,7 +613,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
             self.visit_ty(&field.ty);
         }
 
-        self.process_generic_params(ty_params, item.span, &qualname, item.id);
+        self.process_generic_params(ty_params, &qualname, item.id);
     }
 
     fn process_enum(
@@ -642,10 +634,10 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
         for variant in &enum_definition.variants {
             let name = variant.node.ident.name.to_string();
             let qualname = format!("{}::{}", enum_data.qualname, name);
+            let name_span = variant.node.ident.span;
 
             match variant.node.data {
                 ast::VariantData::Struct(ref fields, _) => {
-                    let sub_span = self.span.span_for_first_ident(variant.span);
                     let fields_str = fields
                         .iter()
                         .enumerate()
@@ -655,9 +647,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
                         .collect::<Vec<_>>()
                         .join(", ");
                     let value = format!("{}::{} {{ {} }}", enum_data.name, name, fields_str);
-                    if !self.span.filter_generated(sub_span, variant.span) {
-                        let span = self
-                            .span_from_span(sub_span.expect("No span found for struct variant"));
+                    if !self.span.filter_generated(name_span) {
+                        let span = self.span_from_span(name_span);
                         let id = ::id_from_node_id(variant.node.data.id(), &self.save_ctxt);
                         let parent = Some(::id_from_node_id(item.id, &self.save_ctxt));
 
@@ -684,7 +675,6 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
                     }
                 }
                 ref v => {
-                    let sub_span = self.span.span_for_first_ident(variant.span);
                     let mut value = format!("{}::{}", enum_data.name, name);
                     if let &ast::VariantData::Tuple(ref fields, _) = v {
                         value.push('(');
@@ -695,9 +685,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
                             .join(", "));
                         value.push(')');
                     }
-                    if !self.span.filter_generated(sub_span, variant.span) {
-                        let span =
-                            self.span_from_span(sub_span.expect("No span found for tuple variant"));
+                    if !self.span.filter_generated(name_span) {
+                        let span = self.span_from_span(name_span);
                         let id = ::id_from_node_id(variant.node.data.id(), &self.save_ctxt);
                         let parent = Some(::id_from_node_id(item.id, &self.save_ctxt));
 
@@ -731,7 +720,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
                 self.visit_ty(&field.ty);
             }
         }
-        self.process_generic_params(ty_params, item.span, &enum_data.qualname, item.id);
+        self.process_generic_params(ty_params, &enum_data.qualname, item.id);
         self.dumper.dump_def(&access, enum_data);
     }
 
@@ -755,7 +744,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
         if let &Some(ref trait_ref) = trait_ref {
             self.process_path(trait_ref.ref_id, &trait_ref.path);
         }
-        self.process_generic_params(type_parameters, item.span, "", item.id);
+        self.process_generic_params(type_parameters, "", item.id);
         for impl_item in impl_items {
             let map = &self.tcx.hir;
             self.process_impl_item(impl_item, map.local_def_id(item.id));
@@ -779,10 +768,9 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
             val.push_str(": ");
             val.push_str(&bounds_to_string(trait_refs));
         }
-        let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Trait);
-        if !self.span.filter_generated(sub_span, item.span) {
+        if !self.span.filter_generated(item.ident.span) {
             let id = ::id_from_node_id(item.id, &self.save_ctxt);
-            let span = self.span_from_span(sub_span.expect("No span found for trait"));
+            let span = self.span_from_span(item.ident.span);
             let children = methods
                 .iter()
                 .map(|i| ::id_from_node_id(i.id, &self.save_ctxt))
@@ -815,21 +803,18 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
 
             let trait_ref = &trait_ref.trait_ref;
             if let Some(id) = self.lookup_def_id(trait_ref.ref_id) {
-                let sub_span = self.span.sub_span_for_type_name(trait_ref.path.span);
-                if !self.span.filter_generated(sub_span, trait_ref.path.span) {
-                    let span = self.span_from_span(sub_span.expect("No span found for trait ref"));
+                let sub_span = trait_ref.path.segments.last().unwrap().ident.span;
+                if !self.span.filter_generated(sub_span) {
+                    let span = self.span_from_span(sub_span);
                     self.dumper.dump_ref(Ref {
                         kind: RefKind::Type,
-                        span,
+                        span: span.clone(),
                         ref_id: ::id_from_def_id(id),
                     });
-                }
 
-                if !self.span.filter_generated(sub_span, trait_ref.path.span) {
-                    let sub_span = self.span_from_span(sub_span.expect("No span for inheritance"));
                     self.dumper.dump_relation(Relation {
                         kind: RelationKind::SuperTrait,
-                        span: sub_span,
+                        span,
                         from: ::id_from_def_id(id),
                         to: ::id_from_node_id(item.id, &self.save_ctxt),
                     });
@@ -838,7 +823,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
         }
 
         // walk generics and methods
-        self.process_generic_params(generics, item.span, &qualname, item.id);
+        self.process_generic_params(generics, &qualname, item.id);
         for method in methods {
             let map = &self.tcx.hir;
             self.process_trait_item(method, map.local_def_id(item.id))
@@ -988,12 +973,10 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
                 };
                 let variant = adt.variant_of_def(self.save_ctxt.get_path_def(p.id));
 
-                for &Spanned { node: ref field, span } in fields {
-                    let sub_span = self.span.span_for_first_ident(span);
+                for &Spanned { node: ref field, .. } in fields {
                     if let Some(index) = self.tcx.find_field_index(field.ident, variant) {
-                        if !self.span.filter_generated(sub_span, span) {
-                            let span =
-                                self.span_from_span(sub_span.expect("No span fund for var ref"));
+                        if !self.span.filter_generated(field.ident.span) {
+                            let span = self.span_from_span(field.ident.span);
                             self.dumper.dump_ref(Ref {
                                 kind: RefKind::Variable,
                                 span,
@@ -1034,7 +1017,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
                     value.push_str(": ");
                     value.push_str(&typ);
 
-                    if !self.span.filter_generated(Some(ident.span), ident.span) {
+                    if !self.span.filter_generated(ident.span) {
                         let qualname = format!("{}${}", ident.to_string(), id);
                         let id = ::id_from_node_id(id, &self.save_ctxt);
                         let span = self.span_from_span(ident.span);
@@ -1109,14 +1092,11 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
                 None => String::new(),
             };
 
-            // Get the span only for the name of the variable (I hope the path
-            // is only ever a variable name, but who knows?).
-            let sub_span = self.span.span_for_last_ident(ident.span);
             // Rust uses the id of the pattern for var lookups, so we'll use it too.
-            if !self.span.filter_generated(sub_span, ident.span) {
+            if !self.span.filter_generated(ident.span) {
                 let qualname = format!("{}${}", ident.to_string(), id);
                 let id = ::id_from_node_id(id, &self.save_ctxt);
-                let span = self.span_from_span(sub_span.expect("No span found for variable"));
+                let span = self.span_from_span(ident.span);
 
                 self.dumper.dump_def(
                     &Access {
@@ -1190,8 +1170,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
             ast::TraitItemKind::Const(ref ty, ref expr) => {
                 self.process_assoc_const(
                     trait_item.id,
-                    trait_item.ident.name,
-                    trait_item.span,
+                    trait_item.ident,
                     &ty,
                     expr.as_ref().map(|e| &**e),
                     trait_id,
@@ -1214,11 +1193,9 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
                 // FIXME do something with _bounds (for type refs)
                 let name = trait_item.ident.name.to_string();
                 let qualname = format!("::{}", self.tcx.node_path_str(trait_item.id));
-                let sub_span = self.span
-                    .sub_span_after_keyword(trait_item.span, keywords::Type);
 
-                if !self.span.filter_generated(sub_span, trait_item.span) {
-                    let span = self.span_from_span(sub_span.expect("No span found for assoc type"));
+                if !self.span.filter_generated(trait_item.ident.span) {
+                    let span = self.span_from_span(trait_item.ident.span);
                     let id = ::id_from_node_id(trait_item.id, &self.save_ctxt);
 
                     self.dumper.dump_def(
@@ -1263,8 +1240,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
             ast::ImplItemKind::Const(ref ty, ref expr) => {
                 self.process_assoc_const(
                     impl_item.id,
-                    impl_item.ident.name,
-                    impl_item.span,
+                    impl_item.ident,
                     &ty,
                     Some(expr),
                     impl_id,
@@ -1328,7 +1304,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
             .map(::id_from_def_id);
 
         match use_tree.kind {
-            ast::UseTreeKind::Simple(..) => {
+            ast::UseTreeKind::Simple(alias, ..) => {
                 let ident = use_tree.ident();
                 let path = ast::Path {
                     segments: prefix.segments
@@ -1339,16 +1315,14 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
                     span: path.span,
                 };
 
-                let sub_span = self.span.span_for_last_ident(path.span);
-                let alias_span = self.span.sub_span_after_keyword(use_tree.span, keywords::As);
-                let ref_id = self.lookup_def_id(id);
-
-                if !self.span.filter_generated(sub_span, path.span) {
-                    let span = self.span_from_span(sub_span.expect("No span found for use"));
-                    let alias_span = alias_span.map(|sp| self.span_from_span(sp));
+                let sub_span = path.segments.last().unwrap().ident.span;
+                if !self.span.filter_generated(sub_span) {
+                    let ref_id = self.lookup_def_id(id).map(|id| ::id_from_def_id(id));
+                    let alias_span = alias.map(|i| self.span_from_span(i.span));
+                    let span = self.span_from_span(sub_span);
                     self.dumper.import(&access, Import {
                         kind: ImportKind::Use,
-                        ref_id: ref_id.map(|id| ::id_from_def_id(id)),
+                        ref_id,
                         span,
                         alias_span,
                         name: ident.to_string(),
@@ -1377,9 +1351,9 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
                     Vec::new()
                 };
 
-                let sub_span = self.span.sub_span_of_token(use_tree.span,
-                                                           token::BinOp(token::Star));
-                if !self.span.filter_generated(sub_span, use_tree.span) {
+                let sub_span =
+                    self.span.sub_span_of_token(use_tree.span, token::BinOp(token::Star));
+                if !self.span.filter_generated(use_tree.span) {
                     let span =
                         self.span_from_span(sub_span.expect("No span found for use glob"));
                     self.dumper.import(&access, Import {
@@ -1471,11 +1445,9 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
                 self.process_use_tree(use_tree, item.id, item, &prefix);
             }
             ExternCrate(_) => {
-                let alias_span = self.span.span_for_last_ident(item.span);
-
-                if !self.span.filter_generated(alias_span, item.span) {
-                    let span =
-                        self.span_from_span(alias_span.expect("No span found for extern crate"));
+                let name_span = item.ident.span;
+                if !self.span.filter_generated(name_span) {
+                    let span = self.span_from_span(name_span);
                     let parent = self.save_ctxt.tcx.hir.opt_local_def_id(item.id)
                         .and_then(|id| self.save_ctxt.tcx.parent_def_id(id))
                         .map(::id_from_def_id);
@@ -1518,9 +1490,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
             Ty(ref ty, ref ty_params) => {
                 let qualname = format!("::{}", self.tcx.node_path_str(item.id));
                 let value = ty_to_string(&ty);
-                let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Type);
-                if !self.span.filter_generated(sub_span, item.span) {
-                    let span = self.span_from_span(sub_span.expect("No span found for typedef"));
+                if !self.span.filter_generated(item.ident.span) {
+                    let span = self.span_from_span(item.ident.span);
                     let id = ::id_from_node_id(item.id, &self.save_ctxt);
 
                     self.dumper.dump_def(
@@ -1543,15 +1514,14 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
                 }
 
                 self.visit_ty(&ty);
-                self.process_generic_params(ty_params, item.span, &qualname, item.id);
+                self.process_generic_params(ty_params, &qualname, item.id);
             }
             Existential(ref _bounds, ref ty_params) => {
                 let qualname = format!("::{}", self.tcx.node_path_str(item.id));
                 // FIXME do something with _bounds
                 let value = String::new();
-                let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Type);
-                if !self.span.filter_generated(sub_span, item.span) {
-                    let span = self.span_from_span(sub_span.expect("No span found for typedef"));
+                if !self.span.filter_generated(item.ident.span) {
+                    let span = self.span_from_span(item.ident.span);
                     let id = ::id_from_node_id(item.id, &self.save_ctxt);
 
                     self.dumper.dump_def(
@@ -1573,7 +1543,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
                     );
                 }
 
-                self.process_generic_params(ty_params, item.span, &qualname, item.id);
+                self.process_generic_params(ty_params, &qualname, item.id);
             }
             Mac(_) => (),
             _ => visit::walk_item(self, item),
@@ -1606,14 +1576,13 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
                 }
 
                 if let Some(id) = self.lookup_def_id(t.id) {
-                    if let Some(sub_span) = self.span.sub_span_for_type_name(t.span) {
-                        let span = self.span_from_span(sub_span);
-                        self.dumper.dump_ref(Ref {
-                            kind: RefKind::Type,
-                            span,
-                            ref_id: ::id_from_def_id(id),
-                        });
-                    }
+                    let sub_span = path.segments.last().unwrap().ident.span;
+                    let span = self.span_from_span(sub_span);
+                    self.dumper.dump_ref(Ref {
+                        kind: RefKind::Type,
+                        span,
+                        ref_id: ::id_from_def_id(id),
+                    });
                 }
 
                 self.write_sub_paths_truncated(path);
@@ -1757,7 +1726,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
                         item.id,
                         |v| v.process_formals(&decl.inputs, &fn_data.qualname),
                     );
-                    self.process_generic_params(generics, item.span, &fn_data.qualname, item.id);
+                    self.process_generic_params(generics, &fn_data.qualname, item.id);
                     self.dumper.dump_def(&access, fn_data);
                 }
 
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index 4b43a1a6270..99117237014 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -60,9 +60,7 @@ use std::path::{Path, PathBuf};
 use syntax::ast::{self, Attribute, NodeId, PatKind};
 use syntax::source_map::Spanned;
 use syntax::parse::lexer::comments::strip_doc_comment_decoration;
-use syntax::parse::token;
 use syntax::print::pprust;
-use syntax::symbol::keywords;
 use syntax::visit::{self, Visitor};
 use syntax::print::pprust::{arg_to_string, ty_to_string};
 use syntax::source_map::MacroAttribute;
@@ -162,14 +160,12 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
         let qualname = format!("::{}", self.tcx.node_path_str(item.id));
         match item.node {
             ast::ForeignItemKind::Fn(ref decl, ref generics) => {
-                let sub_span = self.span_utils
-                    .sub_span_after_keyword(item.span, keywords::Fn);
-                filter!(self.span_utils, sub_span, item.span, None);
+                filter!(self.span_utils, item.ident.span);
 
                 Some(Data::DefData(Def {
                     kind: DefKind::ForeignFunction,
                     id: id_from_node_id(item.id, self),
-                    span: self.span_from_span(sub_span.unwrap()),
+                    span: self.span_from_span(item.ident.span),
                     name: item.ident.to_string(),
                     qualname,
                     value: make_signature(decl, generics),
@@ -181,13 +177,11 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                     attributes: lower_attributes(item.attrs.clone(), self),
                 }))
             }
-            ast::ForeignItemKind::Static(ref ty, m) => {
-                let keyword = if m { keywords::Mut } else { keywords::Static };
-                let sub_span = self.span_utils.sub_span_after_keyword(item.span, keyword);
-                filter!(self.span_utils, sub_span, item.span, None);
+            ast::ForeignItemKind::Static(ref ty, _) => {
+                filter!(self.span_utils, item.ident.span);
 
                 let id = ::id_from_node_id(item.id, self);
-                let span = self.span_from_span(sub_span.unwrap());
+                let span = self.span_from_span(item.ident.span);
 
                 Some(Data::DefData(Def {
                     kind: DefKind::ForeignStatic,
@@ -214,13 +208,11 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
         match item.node {
             ast::ItemKind::Fn(ref decl, .., ref generics, _) => {
                 let qualname = format!("::{}", self.tcx.node_path_str(item.id));
-                let sub_span = self.span_utils
-                    .sub_span_after_keyword(item.span, keywords::Fn);
-                filter!(self.span_utils, sub_span, item.span, None);
+                filter!(self.span_utils, item.ident.span);
                 Some(Data::DefData(Def {
                     kind: DefKind::Function,
                     id: id_from_node_id(item.id, self),
-                    span: self.span_from_span(sub_span.unwrap()),
+                    span: self.span_from_span(item.ident.span),
                     name: item.ident.to_string(),
                     qualname,
                     value: make_signature(decl, generics),
@@ -232,19 +224,13 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                     attributes: lower_attributes(item.attrs.clone(), self),
                 }))
             }
-            ast::ItemKind::Static(ref typ, mt, _) => {
+            ast::ItemKind::Static(ref typ, ..) => {
                 let qualname = format!("::{}", self.tcx.node_path_str(item.id));
 
-                let keyword = match mt {
-                    ast::Mutability::Mutable => keywords::Mut,
-                    ast::Mutability::Immutable => keywords::Static,
-                };
-
-                let sub_span = self.span_utils.sub_span_after_keyword(item.span, keyword);
-                filter!(self.span_utils, sub_span, item.span, None);
+                filter!(self.span_utils, item.ident.span);
 
                 let id = id_from_node_id(item.id, self);
-                let span = self.span_from_span(sub_span.unwrap());
+                let span = self.span_from_span(item.ident.span);
 
                 Some(Data::DefData(Def {
                     kind: DefKind::Static,
@@ -263,12 +249,10 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
             }
             ast::ItemKind::Const(ref typ, _) => {
                 let qualname = format!("::{}", self.tcx.node_path_str(item.id));
-                let sub_span = self.span_utils
-                    .sub_span_after_keyword(item.span, keywords::Const);
-                filter!(self.span_utils, sub_span, item.span, None);
+                filter!(self.span_utils, item.ident.span);
 
                 let id = id_from_node_id(item.id, self);
-                let span = self.span_from_span(sub_span.unwrap());
+                let span = self.span_from_span(item.ident.span);
 
                 Some(Data::DefData(Def {
                     kind: DefKind::Const,
@@ -291,16 +275,14 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                 let cm = self.tcx.sess.source_map();
                 let filename = cm.span_to_filename(m.inner);
 
-                let sub_span = self.span_utils
-                    .sub_span_after_keyword(item.span, keywords::Mod);
-                filter!(self.span_utils, sub_span, item.span, None);
+                filter!(self.span_utils, item.ident.span);
 
                 Some(Data::DefData(Def {
                     kind: DefKind::Mod,
                     id: id_from_node_id(item.id, self),
                     name: item.ident.to_string(),
                     qualname,
-                    span: self.span_from_span(sub_span.unwrap()),
+                    span: self.span_from_span(item.ident.span),
                     value: filename.to_string(),
                     parent: None,
                     children: m.items
@@ -316,9 +298,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
             ast::ItemKind::Enum(ref def, _) => {
                 let name = item.ident.to_string();
                 let qualname = format!("::{}", self.tcx.node_path_str(item.id));
-                let sub_span = self.span_utils
-                    .sub_span_after_keyword(item.span, keywords::Enum);
-                filter!(self.span_utils, sub_span, item.span, None);
+                filter!(self.span_utils, item.ident.span);
                 let variants_str = def.variants
                     .iter()
                     .map(|v| v.node.ident.to_string())
@@ -328,7 +308,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                 Some(Data::DefData(Def {
                     kind: DefKind::Enum,
                     id: id_from_node_id(item.id, self),
-                    span: self.span_from_span(sub_span.unwrap()),
+                    span: self.span_from_span(item.ident.span),
                     name,
                     qualname,
                     value,
@@ -349,11 +329,11 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                     if generated_code(path.span) {
                         return None;
                     }
-                    let sub_span = self.span_utils.sub_span_for_type_name(path.span);
-                    filter!(self.span_utils, sub_span, typ.span, None);
+                    let sub_span = path.segments.last().unwrap().ident.span;
+                    filter!(self.span_utils, sub_span);
 
                     let impl_id = self.next_impl_id();
-                    let span = self.span_from_span(sub_span.unwrap());
+                    let span = self.span_from_span(sub_span);
 
                     let type_data = self.lookup_ref_id(typ.id);
                     type_data.map(|type_data| {
@@ -402,15 +382,13 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
         if let Some(ident) = field.ident {
             let name = ident.to_string();
             let qualname = format!("::{}::{}", self.tcx.node_path_str(scope), ident);
-            let sub_span = self.span_utils
-                .sub_span_before_token(field.span, token::Colon);
-            filter!(self.span_utils, sub_span, field.span, None);
+            filter!(self.span_utils, ident.span);
             let def_id = self.tcx.hir.local_def_id(field.id);
             let typ = self.tcx.type_of(def_id).to_string();
 
 
             let id = id_from_node_id(field.id, self);
-            let span = self.span_from_span(sub_span.unwrap());
+            let span = self.span_from_span(ident.span);
 
             Some(Def {
                 kind: DefKind::Field,
@@ -433,7 +411,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
 
     // FIXME would be nice to take a MethodItem here, but the ast provides both
     // trait and impl flavours, so the caller must do the disassembly.
-    pub fn get_method_data(&self, id: ast::NodeId, name: ast::Name, span: Span) -> Option<Def> {
+    pub fn get_method_data(&self, id: ast::NodeId, ident: ast::Ident, span: Span) -> Option<Def> {
         // The qualname for a method is the trait name or name of the struct in an impl in
         // which the method is declared in, followed by the method's name.
         let (qualname, parent_scope, decl_id, docs, attributes) =
@@ -459,7 +437,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                                 qualname.push_str(&self.tcx.item_path_str(def_id));
                                 self.tcx
                                     .associated_items(def_id)
-                                    .find(|item| item.ident.name == name)
+                                    .find(|item| item.ident.name == ident.name)
                                     .map(|item| decl_id = Some(item.def_id));
                             }
                             qualname.push_str(">");
@@ -512,16 +490,15 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                 },
             };
 
-        let qualname = format!("{}::{}", qualname, name);
+        let qualname = format!("{}::{}", qualname, ident.name);
 
-        let sub_span = self.span_utils.sub_span_after_keyword(span, keywords::Fn);
-        filter!(self.span_utils, sub_span, span, None);
+        filter!(self.span_utils, ident.span);
 
         Some(Def {
             kind: DefKind::Method,
             id: id_from_node_id(id, self),
-            span: self.span_from_span(sub_span.unwrap()),
-            name: name.to_string(),
+            span: self.span_from_span(ident.span),
+            name: ident.name.to_string(),
             qualname,
             // FIXME you get better data here by using the visitor.
             value: String::new(),
@@ -540,9 +517,9 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
             if generated_code(span) {
                 return None;
             }
-            let sub_span = self.span_utils.sub_span_for_type_name(span).or(Some(span));
-            filter!(self.span_utils, sub_span, span, None);
-            let span = self.span_from_span(sub_span.unwrap());
+            let sub_span = trait_ref.path.segments.last().unwrap().ident.span;
+            filter!(self.span_utils, sub_span);
+            let span = self.span_from_span(sub_span);
             Some(Ref {
                 kind: RefKind::Type,
                 span,
@@ -574,9 +551,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                     ty::Adt(def, _) if !def.is_enum() => {
                         let variant = &def.non_enum_variant();
                         let index = self.tcx.find_field_index(ident, variant).unwrap();
-                        let sub_span = self.span_utils.span_for_last_ident(expr.span);
-                        filter!(self.span_utils, sub_span, expr.span, None);
-                        let span = self.span_from_span(sub_span.unwrap());
+                        filter!(self.span_utils, ident.span);
+                        let span = self.span_from_span(ident.span);
                         return Some(Data::RefData(Ref {
                             kind: RefKind::Variable,
                             span,
@@ -593,9 +569,9 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
             ast::ExprKind::Struct(ref path, ..) => {
                 match self.tables.expr_ty_adjusted(&hir_node).sty {
                     ty::Adt(def, _) if !def.is_enum() => {
-                        let sub_span = self.span_utils.span_for_last_ident(path.span);
-                        filter!(self.span_utils, sub_span, path.span, None);
-                        let span = self.span_from_span(sub_span.unwrap());
+                        let sub_span = path.segments.last().unwrap().ident.span;
+                        filter!(self.span_utils, sub_span);
+                        let span = self.span_from_span(sub_span);
                         Some(Data::RefData(Ref {
                             kind: RefKind::Type,
                             span,
@@ -624,7 +600,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                     ty::TraitContainer(_) => (None, Some(method_id)),
                 };
                 let sub_span = seg.ident.span;
-                filter!(self.span_utils, Some(sub_span), expr.span, None);
+                filter!(self.span_utils, sub_span);
                 let span = self.span_from_span(sub_span);
                 Some(Data::RefData(Ref {
                     kind: RefKind::Function,
@@ -729,7 +705,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
         let def = self.get_path_def(id);
         let last_seg = &path.segments[path.segments.len() - 1];
         let sub_span = last_seg.ident.span;
-        filter!(self.span_utils, Some(sub_span), path.span, None);
+        filter!(self.span_utils, sub_span);
         match def {
             HirDef::Upvar(id, ..) | HirDef::Local(id) => {
                 let span = self.span_from_span(sub_span);
@@ -753,13 +729,11 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
             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),
-                    }
+                let fn_span = path.segments.first().unwrap().ident.span;
+                Some(Ref {
+                    kind: RefKind::Type,
+                    span: self.span_from_span(fn_span),
+                    ref_id: id_from_def_id(def_id),
                 })
             }
             HirDef::Struct(def_id) |
@@ -844,10 +818,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
         variant: &ty::VariantDef,
     ) -> Option<Ref> {
         let index = self.tcx.find_field_index(field_ref.ident, variant).unwrap();
-        // We don't really need a sub-span here, but no harm done
-        let sub_span = self.span_utils.span_for_last_ident(field_ref.ident.span);
-        filter!(self.span_utils, sub_span, field_ref.ident.span, None);
-        let span = self.span_from_span(sub_span.unwrap());
+        filter!(self.span_utils, field_ref.ident.span);
+        let span = self.span_from_span(field_ref.ident.span);
         Some(Ref {
             kind: RefKind::Variable,
             span,
diff --git a/src/librustc_save_analysis/span_utils.rs b/src/librustc_save_analysis/span_utils.rs
index 47677a75171..902353da13f 100644
--- a/src/librustc_save_analysis/span_utils.rs
+++ b/src/librustc_save_analysis/span_utils.rs
@@ -16,7 +16,6 @@ use std::cell::Cell;
 
 use syntax::parse::lexer::{self, StringReader};
 use syntax::parse::token::{self, Token};
-use syntax::symbol::keywords;
 use syntax_pos::*;
 
 #[derive(Clone)]
@@ -67,131 +66,6 @@ impl<'a> SpanUtils<'a> {
         lexer::StringReader::retokenize(&self.sess.parse_sess, span)
     }
 
-    // Re-parses a path and returns the span for the last identifier in the path
-    pub fn span_for_last_ident(&self, span: Span) -> Option<Span> {
-        let mut result = None;
-
-        let mut toks = self.retokenise_span(span);
-        let mut bracket_count = 0;
-        loop {
-            let ts = toks.real_token();
-            if ts.tok == token::Eof {
-                return result;
-            }
-            if bracket_count == 0 && (ts.tok.is_ident() || ts.tok.is_keyword(keywords::SelfValue)) {
-                result = Some(ts.sp);
-            }
-
-            bracket_count += match ts.tok {
-                token::Lt => 1,
-                token::Gt => -1,
-                token::BinOp(token::Shr) => -2,
-                _ => 0,
-            }
-        }
-    }
-
-    // Return the span for the first identifier in the path.
-    pub fn span_for_first_ident(&self, span: Span) -> Option<Span> {
-        let mut toks = self.retokenise_span(span);
-        let mut bracket_count = 0;
-        loop {
-            let ts = toks.real_token();
-            if ts.tok == token::Eof {
-                return None;
-            }
-            if bracket_count == 0 && (ts.tok.is_ident() || ts.tok.is_keyword(keywords::SelfValue)) {
-                return Some(ts.sp);
-            }
-
-            bracket_count += match ts.tok {
-                token::Lt => 1,
-                token::Gt => -1,
-                token::BinOp(token::Shr) => -2,
-                _ => 0,
-            }
-        }
-    }
-
-    // Return the span for the last ident before a `<` and outside any
-    // angle brackets, or the last span.
-    pub fn sub_span_for_type_name(&self, span: Span) -> Option<Span> {
-        let mut toks = self.retokenise_span(span);
-        let mut prev = toks.real_token();
-        let mut result = None;
-
-        // We keep track of the following two counts - the depth of nesting of
-        // angle brackets, and the depth of nesting of square brackets. For the
-        // angle bracket count, we only count tokens which occur outside of any
-        // square brackets (i.e. bracket_count == 0). The intuition here is
-        // that we want to count angle brackets in the type, but not any which
-        // could be in expression context (because these could mean 'less than',
-        // etc.).
-        let mut angle_count = 0;
-        let mut bracket_count = 0;
-        loop {
-            let next = toks.real_token();
-
-            if (next.tok == token::Lt || next.tok == token::Colon) && angle_count == 0
-                && bracket_count == 0 && prev.tok.is_ident()
-            {
-                result = Some(prev.sp);
-            }
-
-            if bracket_count == 0 {
-                angle_count += match prev.tok {
-                    token::Lt => 1,
-                    token::Gt => -1,
-                    token::BinOp(token::Shl) => 2,
-                    token::BinOp(token::Shr) => -2,
-                    _ => 0,
-                };
-            }
-
-            bracket_count += match prev.tok {
-                token::OpenDelim(token::Bracket) => 1,
-                token::CloseDelim(token::Bracket) => -1,
-                _ => 0,
-            };
-
-            if next.tok == token::Eof {
-                break;
-            }
-            prev = next;
-        }
-        #[cfg(debug_assertions)] {
-            if angle_count != 0 || bracket_count != 0 {
-                let loc = self.sess.source_map().lookup_char_pos(span.lo());
-                span_bug!(
-                    span,
-                    "Mis-counted brackets when breaking path? Parsing '{}' in {}, line {}",
-                    self.snippet(span),
-                    loc.file.name,
-                    loc.line
-                );
-            }
-        }
-        if result.is_none() && prev.tok.is_ident() {
-            return Some(prev.sp);
-        }
-        result
-    }
-
-    pub fn sub_span_before_token(&self, span: Span, tok: Token) -> Option<Span> {
-        let mut toks = self.retokenise_span(span);
-        let mut prev = toks.real_token();
-        loop {
-            if prev.tok == token::Eof {
-                return None;
-            }
-            let next = toks.real_token();
-            if next.tok == tok {
-                return Some(prev.sp);
-            }
-            prev = next;
-        }
-    }
-
     pub fn sub_span_of_token(&self, span: Span, tok: Token) -> Option<Span> {
         let mut toks = self.retokenise_span(span);
         loop {
@@ -205,28 +79,6 @@ impl<'a> SpanUtils<'a> {
         }
     }
 
-    pub fn sub_span_after_keyword(&self, span: Span, keyword: keywords::Keyword) -> Option<Span> {
-        self.sub_span_after(span, |t| t.is_keyword(keyword))
-    }
-
-    fn sub_span_after<F: Fn(Token) -> bool>(&self, span: Span, f: F) -> Option<Span> {
-        let mut toks = self.retokenise_span(span);
-        loop {
-            let ts = toks.real_token();
-            if ts.tok == token::Eof {
-                return None;
-            }
-            if f(ts.tok) {
-                let ts = toks.real_token();
-                if ts.tok == token::Eof {
-                    return None;
-                } else {
-                    return Some(ts.sp);
-                }
-            }
-        }
-    }
-
     // // Return the name for a macro definition (identifier after first `!`)
     // pub fn span_for_macro_def_name(&self, span: Span) -> Option<Span> {
     //     let mut toks = self.retokenise_span(span);
@@ -271,42 +123,28 @@ impl<'a> SpanUtils<'a> {
     ///
     /// Used to filter out spans of minimal value,
     /// such as references to macro internal variables.
-    pub fn filter_generated(&self, sub_span: Option<Span>, parent: Span) -> bool {
-        if !generated_code(parent) {
-            // Edge case - this occurs on generated code with incorrect expansion info.
-            return sub_span.is_none()
+    pub fn filter_generated(&self, span: Span) -> bool {
+        if span.is_dummy() {
+            return true;
+        }
+
+        if !generated_code(span) {
+            return false;
         }
-        // If sub_span is none, filter out generated code.
-        let sub_span = match sub_span {
-            Some(ss) => ss,
-            None => return true,
-        };
 
         //If the span comes from a fake source_file, filter it.
-        if !self.sess
+        !self.sess
             .source_map()
-            .lookup_char_pos(parent.lo())
+            .lookup_char_pos(span.lo())
             .file
             .is_real_file()
-        {
-            return true;
-        }
-
-        // Otherwise, a generated span is deemed invalid if it is not a sub-span of the root
-        // callsite. This filters out macro internal variables and most malformed spans.
-        !parent.source_callsite().contains(sub_span)
     }
 }
 
 macro_rules! filter {
-    ($util: expr, $span: expr, $parent: expr, None) => {
-        if $util.filter_generated($span, $parent) {
+    ($util: expr, $parent: expr) => {
+        if $util.filter_generated($parent) {
             return None;
         }
     };
-    ($util: expr, $span: ident, $parent: expr) => {
-        if $util.filter_generated($span, $parent) {
-            return;
-        }
-    };
 }