diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index 31e6a3106a438..d05ede07c3f64 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -148,6 +148,9 @@ pub enum DepNode<D: Clone + Debug> {
     // For proj. cache, we just keep a list of all def-ids, since it is
     // not a hotspot.
     ProjectionCache { def_ids: Vec<D> },
+
+    DescribeDef(D),
+    DefSpan(D),
 }
 
 impl<D: Clone + Debug> DepNode<D> {
@@ -253,6 +256,8 @@ impl<D: Clone + Debug> DepNode<D> {
                 let def_ids: Option<Vec<E>> = def_ids.iter().map(op).collect();
                 def_ids.map(|d| ProjectionCache { def_ids: d })
             }
+            DescribeDef(ref d) => op(d).map(DescribeDef),
+            DefSpan(ref d) => op(d).map(DefSpan),
         }
     }
 }
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index 0358319256760..0b43e65ddbf82 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -181,7 +181,6 @@ pub trait CrateStore {
     fn crate_data_as_rc_any(&self, krate: CrateNum) -> Rc<Any>;
 
     // item info
-    fn def_span(&self, sess: &Session, def: DefId) -> Span;
     fn stability(&self, def: DefId) -> Option<attr::Stability>;
     fn deprecation(&self, def: DefId) -> Option<attr::Deprecation>;
     fn visibility(&self, def: DefId) -> ty::Visibility;
@@ -312,7 +311,6 @@ impl CrateStore for DummyCrateStore {
     fn crate_data_as_rc_any(&self, krate: CrateNum) -> Rc<Any>
         { bug!("crate_data_as_rc_any") }
     // item info
-    fn def_span(&self, sess: &Session, def: DefId) -> Span { bug!("def_span") }
     fn stability(&self, def: DefId) -> Option<attr::Stability> { bug!("stability") }
     fn deprecation(&self, def: DefId) -> Option<attr::Deprecation> { bug!("deprecation") }
     fn visibility(&self, def: DefId) -> ty::Visibility { bug!("visibility") }
diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs
index 1749c90b5892a..76398294aca36 100644
--- a/src/librustc/ty/maps.rs
+++ b/src/librustc/ty/maps.rs
@@ -285,6 +285,12 @@ impl<'tcx> QueryDescription for queries::describe_def<'tcx> {
     }
 }
 
+impl<'tcx> QueryDescription for queries::def_span<'tcx> {
+    fn describe(_: TyCtxt, _: DefId) -> String {
+        bug!("def_span")
+    }
+}
+
 macro_rules! define_maps {
     (<$tcx:tt>
      $($(#[$attr:meta])*
@@ -359,8 +365,10 @@ macro_rules! define_maps {
                 }
 
                 // FIXME(eddyb) Get more valid Span's on queries.
-                if span == DUMMY_SP {
-                    span = key.default_span(tcx);
+                // def_span guard is necesary to prevent a recursive loop,
+                // default_span calls def_span query internally.
+                if span == DUMMY_SP && stringify!($name) != "def_span" {
+                    span = key.default_span(tcx)
                 }
 
                 let _task = tcx.dep_graph.in_task(Self::to_dep_node(&key));
@@ -568,7 +576,8 @@ define_maps! { <'tcx>
     [] def_symbol_name: SymbolName(DefId) -> ty::SymbolName,
     [] symbol_name: symbol_name_dep_node(ty::Instance<'tcx>) -> ty::SymbolName,
 
-    [] describe_def: meta_data_node(DefId) -> Option<Def>
+    [] describe_def: DescribeDef(DefId) -> Option<Def>,
+    [] def_span: DefSpan(DefId) -> Span
 }
 
 fn coherent_trait_dep_node((_, def_id): (CrateNum, DefId)) -> DepNode<DefId> {
@@ -599,8 +608,4 @@ fn typeck_item_bodies_dep_node(_: CrateNum) -> DepNode<DefId> {
 
 fn const_eval_dep_node((def_id, _): (DefId, &Substs)) -> DepNode<DefId> {
     DepNode::ConstEval(def_id)
-}
-
-fn meta_data_node(def_id: DefId) -> DepNode<DefId> {
-    DepNode::MetaData(def_id)
-}
+}
\ No newline at end of file
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index ff4bded012e9e..8be3e4be7c8b7 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -2285,14 +2285,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         }
     }
 
-    pub fn def_span(self, def_id: DefId) -> Span {
-        if let Some(id) = self.hir.as_local_node_id(def_id) {
-            self.hir.span(id)
-        } else {
-            self.sess.cstore.def_span(&self.sess, def_id)
-        }
-    }
-
     pub fn vis_is_accessible_from(self, vis: Visibility, block: NodeId) -> bool {
         vis.is_accessible_from(self.hir.local_def_id(self.hir.get_module_parent(block)), self)
     }
@@ -2694,12 +2686,17 @@ fn associated_item_def_ids<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     Rc::new(vec)
 }
 
+fn def_span<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Span {
+    tcx.hir.span_if_local(def_id).unwrap()
+}
+
 pub fn provide(providers: &mut ty::maps::Providers) {
     *providers = ty::maps::Providers {
         associated_item,
         associated_item_def_ids,
         adt_sized_constraint,
         adt_dtorck_constraint,
+        def_span,
         ..*providers
     };
 }
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index 8bfe3ec1bd5d0..36b993aad69bb 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -114,6 +114,7 @@ provide! { <'tcx> tcx, def_id, cdata
     inherent_impls => { Rc::new(cdata.get_inherent_implementations_for_type(def_id.index)) }
     is_foreign_item => { cdata.is_foreign_item(def_id.index) }
     describe_def => { cdata.get_def(def_id.index) }
+    def_span => { cdata.get_span(def_id.index, &tcx.sess) }
 }
 
 impl CrateStore for cstore::CStore {
@@ -121,11 +122,6 @@ impl CrateStore for cstore::CStore {
         self.get_crate_data(krate)
     }
 
-    fn def_span(&self, sess: &Session, def: DefId) -> Span {
-        self.dep_graph.read(DepNode::MetaData(def));
-        self.get_crate_data(def.krate).get_span(def.index, sess)
-    }
-
     fn stability(&self, def: DefId) -> Option<attr::Stability> {
         self.dep_graph.read(DepNode::MetaData(def));
         self.get_crate_data(def.krate).get_stability(def.index)