Repository: rust-analyzer/rust-analyzer
Pull request #1393 (2019-06-11 13:25:59)

fix: support existential type
Closes https://github.com/rust-analyzer/rust-analyzer/issues/1387
r? @matklad 


Patch:
diff --git a/Cargo.lock b/Cargo.lock
index 2c1c7099e9..579daecf18 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1058,7 +1058,7 @@ dependencies = [
  "ra_syntax 0.1.0",
  "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "salsa 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "salsa 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "test_utils 0.1.0",
 ]
 
@@ -1478,12 +1478,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "salsa"
-version = "0.12.3"
+version = "0.12.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lock_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2126,7 +2125,7 @@ dependencies = [
 "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8"
 "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
 "checksum ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "b96a9549dc8d48f2c283938303c4b5a77aa29bfbc5b54b084fb1630408899a8f"
-"checksum salsa 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2891cd628406e8a0ca714b827511de1bff76f796e3382cc72a3de732ccad5aea"
+"checksum salsa 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2208fabe493ad352dc4f544c482b39e9b9a2c1719d9aa4a0f5e828a61210956"
 "checksum salsa-macros 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b7f1e25ca2b995bdf032946174929d62156ffd57abd7ff88dc6f9bdeb5ac0c59"
 "checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267"
 "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
diff --git a/crates/ra_assists/src/add_missing_impl_members.rs b/crates/ra_assists/src/add_missing_impl_members.rs
index 0e49b04014..23c01e7476 100644
--- a/crates/ra_assists/src/add_missing_impl_members.rs
+++ b/crates/ra_assists/src/add_missing_impl_members.rs
@@ -1,6 +1,6 @@
 use crate::{Assist, AssistId, AssistCtx, ast_editor::{AstEditor, AstBuilder}};
 
-use hir::{HasSource, db::HirDatabase};
+use hir::db::HirDatabase;
 use ra_syntax::{SmolStr, TreeArc};
 use ra_syntax::ast::{self, AstNode, FnDef, ImplItem, ImplItemKind, NameOwner};
 use ra_db::FilePosition;
@@ -110,7 +110,7 @@ fn resolve_target_trait_def(
         impl_block.target_trait().map(AstNode::syntax).and_then(ast::PathType::cast)?.path()?;
 
     match analyzer.resolve_path(db, &ast_path) {
-        Some(hir::PathResolution::Def(hir::ModuleDef::Trait(def))) => Some(def.source(db).ast),
+        Some(hir::PathResolution::Def(hir::ModuleDef::Trait(def))) => Some(def.source(db).1),
         _ => None,
     }
 }
diff --git a/crates/ra_assists/src/fill_match_arms.rs b/crates/ra_assists/src/fill_match_arms.rs
index a7de6ae9f5..45e327cd4a 100644
--- a/crates/ra_assists/src/fill_match_arms.rs
+++ b/crates/ra_assists/src/fill_match_arms.rs
@@ -1,7 +1,7 @@
 use std::fmt::Write;
 
 use hir::{
-    AdtDef, FieldSource, HasSource,
+    AdtDef, FieldSource,
     db::HirDatabase,
 };
 use ra_syntax::ast::{self, AstNode};
@@ -44,8 +44,8 @@ pub(crate) fn fill_match_arms(mut ctx: AssistCtx<impl HirDatabase>) -> Option<As
                 .into_iter()
                 .map(|field| {
                     let name = field.name(db).to_string();
-                    let src = field.source(db);
-                    match src.ast {
+                    let (_, source) = field.source(db);
+                    match source {
                         FieldSource::Named(_) => name,
                         FieldSource::Pos(_) => "_".to_string(),
                     }
diff --git a/crates/ra_batch/src/lib.rs b/crates/ra_batch/src/lib.rs
index c59821f446..a445dcb4d4 100644
--- a/crates/ra_batch/src/lib.rs
+++ b/crates/ra_batch/src/lib.rs
@@ -7,7 +7,7 @@ use std::collections::HashSet;
 use rustc_hash::FxHashMap;
 
 use ra_db::{
-    CrateGraph, FileId, SourceRoot, SourceRootId, SourceDatabase, salsa::{self, Database},
+    CrateGraph, FileId, SourceRoot, SourceRootId, SourceDatabase, salsa,
 };
 use ra_hir::db;
 use ra_project_model::ProjectWorkspace;
@@ -43,12 +43,6 @@ fn vfs_root_to_id(r: ra_vfs::VfsRoot) -> SourceRootId {
 impl BatchDatabase {
     pub fn load(crate_graph: CrateGraph, vfs: &mut Vfs) -> BatchDatabase {
         let mut db = BatchDatabase { runtime: salsa::Runtime::default() };
-        let lru_cap = std::env::var("RA_LRU_CAP")
-            .ok()
-            .and_then(|it| it.parse::<usize>().ok())
-            .unwrap_or(ra_db::DEFAULT_LRU_CAP);
-        db.query_mut(ra_db::ParseQuery).set_lru_capacity(lru_cap);
-        db.query_mut(ra_hir::db::ParseMacroQuery).set_lru_capacity(lru_cap);
         db.set_crate_graph(Arc::new(crate_graph));
 
         // wait until Vfs has loaded all roots
diff --git a/crates/ra_cli/src/analysis_stats.rs b/crates/ra_cli/src/analysis_stats.rs
index c19976bd26..8bb524ce30 100644
--- a/crates/ra_cli/src/analysis_stats.rs
+++ b/crates/ra_cli/src/analysis_stats.rs
@@ -2,7 +2,7 @@ use std::{collections::HashSet, time::Instant, fmt::Write};
 
 use ra_db::SourceDatabase;
 use ra_batch::BatchDatabase;
-use ra_hir::{Crate, ModuleDef, Ty, ImplItem, HasSource};
+use ra_hir::{Crate, ModuleDef, Ty, ImplItem};
 use ra_syntax::AstNode;
 
 use crate::Result;
@@ -64,10 +64,10 @@ pub fn run(verbose: bool, path: &str, only: Option<&str>) -> Result<()> {
         let name = f.name(&db);
         let mut msg = format!("processing: {}", name);
         if verbose {
-            let src = f.source(&db);
-            let original_file = src.file_id.original_file(&db);
+            let (file_id, source) = f.source(&db);
+            let original_file = file_id.original_file(&db);
             let path = db.file_relative_path(original_file);
-            let syntax_range = src.ast.syntax().range();
+            let syntax_range = source.syntax().range();
             write!(msg, " ({:?} {})", path, syntax_range).unwrap();
         }
         bar.set_message(&msg);
diff --git a/crates/ra_db/Cargo.toml b/crates/ra_db/Cargo.toml
index f73dd739a4..827855b2fb 100644
--- a/crates/ra_db/Cargo.toml
+++ b/crates/ra_db/Cargo.toml
@@ -5,7 +5,7 @@ version = "0.1.0"
 authors = ["rust-analyzer developers"]
 
 [dependencies]
-salsa = "0.12.3"
+salsa = "0.12.1"
 relative-path = "0.4.0"
 rustc-hash = "1.0"
 
diff --git a/crates/ra_db/src/lib.rs b/crates/ra_db/src/lib.rs
index f08616100d..7c49c585bc 100644
--- a/crates/ra_db/src/lib.rs
+++ b/crates/ra_db/src/lib.rs
@@ -65,8 +65,6 @@ pub struct FileRange {
     pub range: TextRange,
 }
 
-pub const DEFAULT_LRU_CAP: usize = 128;
-
 /// Database which stores all significant input facts: source code and project
 /// model. Everything else in rust-analyzer is derived from these queries.
 #[salsa::query_group(SourceDatabaseStorage)]
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs
index b3843b35c2..38ff1d6f63 100644
--- a/crates/ra_hir/src/adt.rs
+++ b/crates/ra_hir/src/adt.rs
@@ -11,7 +11,7 @@ use ra_syntax::{
 
 use crate::{
     Name, AsName, Struct, Union, Enum, EnumVariant, Crate, AstDatabase,
-    HirDatabase, StructField, FieldSource, Source, HasSource,
+    HirDatabase, HirFileId, StructField, FieldSource,
     type_ref::TypeRef, DefDatabase,
 };
 
@@ -59,8 +59,8 @@ impl StructData {
         db: &(impl DefDatabase + AstDatabase),
         struct_: Struct,
     ) -> Arc<StructData> {
-        let src = struct_.source(db);
-        Arc::new(StructData::new(&*src.ast))
+        let (_, struct_def) = struct_.source(db);
+        Arc::new(StructData::new(&*struct_def))
     }
 }
 
@@ -72,15 +72,15 @@ impl EnumVariant {
     pub(crate) fn source_impl(
         &self,
         db: &(impl DefDatabase + AstDatabase),
-    ) -> Source<TreeArc<ast::EnumVariant>> {
-        let src = self.parent.source(db);
-        let ast = variants(&*src.ast)
+    ) -> (HirFileId, TreeArc<ast::EnumVariant>) {
+        let (file_id, enum_def) = self.parent.source(db);
+        let var = variants(&*enum_def)
             .zip(db.enum_data(self.parent).variants.iter())
             .find(|(_syntax, (id, _))| *id == self.id)
             .unwrap()
             .0
             .to_owned();
-        Source { file_id: src.file_id, ast }
+        (file_id, var)
     }
     pub(crate) fn variant_data(&self, db: &impl DefDatabase) -> Arc<VariantData> {
         db.enum_data(self.parent).variants[self.id].variant_data.clone()
@@ -95,9 +95,9 @@ pub struct EnumData {
 
 impl EnumData {
     pub(crate) fn enum_data_query(db: &(impl DefDatabase + AstDatabase), e: Enum) -> Arc<EnumData> {
-        let src = e.source(db);
-        let name = src.ast.name().map(|n| n.as_name());
-        let variants = variants(&*src.ast)
+        let (_file_id, enum_def) = e.source(db);
+        let name = enum_def.name().map(|n| n.as_name());
+        let variants = variants(&*enum_def)
             .map(|var| EnumVariantData {
                 name: var.name().map(|it| it.as_name()),
                 variant_data: Arc::new(VariantData::new(var.kind())),
@@ -201,19 +201,24 @@ impl VariantDef {
 }
 
 impl StructField {
-    pub(crate) fn source_impl(&self, db: &(impl DefDatabase + AstDatabase)) -> Source<FieldSource> {
+    pub(crate) fn source_impl(
+        &self,
+        db: &(impl DefDatabase + AstDatabase),
+    ) -> (HirFileId, FieldSource) {
         let var_data = self.parent.variant_data(db);
         let fields = var_data.fields().unwrap();
         let ss;
         let es;
         let (file_id, struct_kind) = match self.parent {
             VariantDef::Struct(s) => {
-                ss = s.source(db);
-                (ss.file_id, ss.ast.kind())
+                let (file_id, source) = s.source(db);
+                ss = source;
+                (file_id, ss.kind())
             }
             VariantDef::EnumVariant(e) => {
-                es = e.source(db);
-                (es.file_id, es.ast.kind())
+                let (file_id, source) = e.source(db);
+                es = source;
+                (file_id, es.kind())
             }
         };
 
@@ -226,12 +231,12 @@ impl StructField {
             }
             ast::StructKind::Unit => Vec::new(),
         };
-        let ast = field_sources
+        let field = field_sources
             .into_iter()
             .zip(fields.iter())
             .find(|(_syntax, (id, _))| *id == self.id)
             .unwrap()
             .0;
-        Source { file_id, ast }
+        (file_id, field)
     }
 }
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 830aea1f33..27850028b7 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -1,13 +1,10 @@
-pub(crate) mod src;
-pub(crate) mod docs;
-
 use std::sync::Arc;
 
 use ra_db::{CrateId, SourceRootId, Edition, FileId};
 use ra_syntax::{ast::{self, NameOwner, TypeAscriptionOwner}, TreeArc};
 
 use crate::{
-    Name, AsName, AstId, Ty, Either, KnownName, HasSource,
+    Name, AsName, AstId, Ty, HirFileId, Either, KnownName,
     HirDatabase, DefDatabase, AstDatabase,
     type_ref::TypeRef,
     nameres::{ModuleScope, Namespace, ImportId, CrateModuleId},
@@ -182,15 +179,40 @@ impl Module {
         })
     }
 
+    /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items.
+    pub fn definition_source(
+        self,
+        db: &(impl DefDatabase + AstDatabase),
+    ) -> (HirFileId, ModuleSource) {
+        let def_map = db.crate_def_map(self.krate);
+        let decl_id = def_map[self.module_id].declaration;
+        let file_id = def_map[self.module_id].definition;
+        let module_source = ModuleSource::new(db, file_id, decl_id);
+        let file_id = file_id.map(HirFileId::from).unwrap_or_else(|| decl_id.unwrap().file_id());
+        (file_id, module_source)
+    }
+
+    /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`.
+    /// `None` for the crate root.
+    pub fn declaration_source(
+        self,
+        db: &(impl DefDatabase + AstDatabase),
+    ) -> Option<(HirFileId, TreeArc<ast::Module>)> {
+        let def_map = db.crate_def_map(self.krate);
+        let decl = def_map[self.module_id].declaration?;
+        let ast = decl.to_node(db);
+        Some((decl.file_id(), ast))
+    }
+
     /// Returns the syntax of the last path segment corresponding to this import
     pub fn import_source(
         self,
         db: &impl HirDatabase,
         import: ImportId,
     ) -> Either<TreeArc<ast::UseTree>, TreeArc<ast::ExternCrateItem>> {
-        let src = self.definition_source(db);
-        let (_, source_map) = db.raw_items_with_source_map(src.file_id);
-        source_map.get(&src.ast, import)
+        let (file_id, source) = self.definition_source(db);
+        let (_, source_map) = db.raw_items_with_source_map(file_id);
+        source_map.get(&source, import)
     }
 
     /// Returns the crate this module is part of.
@@ -313,6 +335,10 @@ impl StructField {
         self.parent.variant_data(db).fields().unwrap()[self.id].name.clone()
     }
 
+    pub fn source(&self, db: &(impl DefDatabase + AstDatabase)) -> (HirFileId, FieldSource) {
+        self.source_impl(db)
+    }
+
     pub fn ty(&self, db: &impl HirDatabase) -> Ty {
         db.type_for_field(*self)
     }
@@ -328,6 +354,13 @@ pub struct Struct {
 }
 
 impl Struct {
+    pub fn source(
+        self,
+        db: &(impl DefDatabase + AstDatabase),
+    ) -> (HirFileId, TreeArc<ast::StructDef>) {
+        self.id.source(db)
+    }
+
     pub fn module(self, db: &impl HirDatabase) -> Module {
         self.id.module(db)
     }
@@ -382,6 +415,13 @@ pub struct Union {
 }
 
 impl Union {
+    pub fn source(
+        self,
+        db: &(impl DefDatabase + AstDatabase),
+    ) -> (HirFileId, TreeArc<ast::StructDef>) {
+        self.id.source(db)
+    }
+
     pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
         db.struct_data(Struct { id: self.id }).name.clone()
     }
@@ -408,6 +448,13 @@ pub struct Enum {
 }
 
 impl Enum {
+    pub fn source(
+        self,
+        db: &(impl DefDatabase + AstDatabase),
+    ) -> (HirFileId, TreeArc<ast::EnumDef>) {
+        self.id.source(db)
+    }
+
     pub fn module(self, db: &impl HirDatabase) -> Module {
         self.id.module(db)
     }
@@ -451,6 +498,12 @@ pub struct EnumVariant {
 }
 
 impl EnumVariant {
+    pub fn source(
+        &self,
+        db: &(impl DefDatabase + AstDatabase),
+    ) -> (HirFileId, TreeArc<ast::EnumVariant>) {
+        self.source_impl(db)
+    }
     pub fn module(&self, db: &impl HirDatabase) -> Module {
         self.parent.module(db)
     }
@@ -535,11 +588,11 @@ impl FnSignature {
         db: &(impl DefDatabase + AstDatabase),
         func: Function,
     ) -> Arc<FnSignature> {
-        let src = func.source(db);
-        let name = src.ast.name().map(|n| n.as_name()).unwrap_or_else(Name::missing);
+        let (_, node) = func.source(db);
+        let name = node.name().map(|n| n.as_name()).unwrap_or_else(Name::missing);
         let mut params = Vec::new();
         let mut has_self_param = false;
-        if let Some(param_list) = src.ast.param_list() {
+        if let Some(param_list) = node.param_list() {
             if let Some(self_param) = param_list.self_param() {
                 let self_type = if let Some(type_ref) = self_param.ascribed_type() {
                     TypeRef::from_ast(type_ref)
@@ -563,7 +616,7 @@ impl FnSignature {
                 params.push(type_ref);
             }
         }
-        let ret_type = if let Some(type_ref) = src.ast.ret_type().and_then(|rt| rt.type_ref()) {
+        let ret_type = if let Some(type_ref) = node.ret_type().and_then(|rt| rt.type_ref()) {
             TypeRef::from_ast(type_ref)
         } else {
             TypeRef::unit()
@@ -592,6 +645,10 @@ impl FnSignature {
 }
 
 impl Function {
+    pub fn source(self, db: &(impl DefDatabase + AstDatabase)) -> (HirFileId, TreeArc<ast::FnDef>) {
+        self.id.source(db)
+    }
+
     pub fn module(self, db: &impl DefDatabase) -> Module {
         self.id.module(db)
     }
@@ -666,6 +723,13 @@ pub struct Const {
 }
 
 impl Const {
+    pub fn source(
+        self,
+        db: &(impl DefDatabase + AstDatabase),
+    ) -> (HirFileId, TreeArc<ast::ConstDef>) {
+        self.id.source(db)
+    }
+
     pub fn module(self, db: &impl DefDatabase) -> Module {
         self.id.module(db)
     }
@@ -716,7 +780,7 @@ impl ConstSignature {
         db: &(impl DefDatabase + AstDatabase),
         konst: Const,
     ) -> Arc<ConstSignature> {
-        let node = konst.source(db).ast;
+        let (_, node) = konst.source(db);
         const_signature_for(&*node)
     }
 
@@ -724,7 +788,7 @@ impl ConstSignature {
         db: &(impl DefDatabase + AstDatabase),
         konst: Static,
     ) -> Arc<ConstSignature> {
-        let node = konst.source(db).ast;
+        let (_, node) = konst.source(db);
         const_signature_for(&*node)
     }
 }
@@ -742,6 +806,13 @@ pub struct Static {
 }
 
 impl Static {
+    pub fn source(
+        self,
+        db: &(impl DefDatabase + AstDatabase),
+    ) -> (HirFileId, TreeArc<ast::StaticDef>) {
+        self.id.source(db)
+    }
+
     pub fn module(self, db: &impl DefDatabase) -> Module {
         self.id.module(db)
     }
@@ -767,6 +838,13 @@ pub struct Trait {
 }
 
 impl Trait {
+    pub fn source(
+        self,
+        db: &(impl DefDatabase + AstDatabase),
+    ) -> (HirFileId, TreeArc<ast::TraitDef>) {
+        self.id.source(db)
+    }
+
     pub fn module(self, db: &impl DefDatabase) -> Module {
         self.id.module(db)
     }
@@ -806,6 +884,13 @@ pub struct TypeAlias {
 }
 
 impl TypeAlias {
+    pub fn source(
+        self,
+        db: &(impl DefDatabase + AstDatabase),
+    ) -> (HirFileId, TreeArc<ast::TypeAliasDef>) {
+        self.id.source(db)
+    }
+
     pub fn module(self, db: &impl DefDatabase) -> Module {
         self.id.module(db)
     }
@@ -854,7 +939,14 @@ pub struct MacroDef {
     pub(crate) id: MacroDefId,
 }
 
-impl MacroDef {}
+impl MacroDef {
+    pub fn source(
+        &self,
+        db: &(impl DefDatabase + AstDatabase),
+    ) -> (HirFileId, TreeArc<ast::MacroCall>) {
+        (self.id.0.file_id(), self.id.0.to_node(db))
+    }
+}
 
 pub enum Container {
     Trait(Trait),
diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs
deleted file mode 100644
index 5785d3b266..0000000000
--- a/crates/ra_hir/src/code_model/src.rs
+++ /dev/null
@@ -1,110 +0,0 @@
-use ra_syntax::{TreeArc, ast};
-
-use crate::{
-    HirFileId, DefDatabase, AstDatabase, Module, ModuleSource,
-    StructField, Struct, Enum, Union, EnumVariant, Function, Static, Trait, Const, TypeAlias,
-    FieldSource, MacroDef, ids::AstItemDef,
-};
-
-pub struct Source<T> {
-    pub file_id: HirFileId,
-    pub ast: T,
-}
-
-pub trait HasSource {
-    type Ast;
-    fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<Self::Ast>;
-}
-
-/// NB: Module is !HasSource, because it has two source nodes at the same time:
-/// definition and declaration.
-impl Module {
-    /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items.
-    pub fn definition_source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ModuleSource> {
-        let def_map = db.crate_def_map(self.krate);
-        let decl_id = def_map[self.module_id].declaration;
-        let file_id = def_map[self.module_id].definition;
-        let ast = ModuleSource::new(db, file_id, decl_id);
-        let file_id = file_id.map(HirFileId::from).unwrap_or_else(|| decl_id.unwrap().file_id());
-        Source { file_id, ast }
-    }
-
-    /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`.
-    /// `None` for the crate root.
-    pub fn declaration_source(
-        self,
-        db: &(impl DefDatabase + AstDatabase),
-    ) -> Option<Source<TreeArc<ast::Module>>> {
-        let def_map = db.crate_def_map(self.krate);
-        let decl = def_map[self.module_id].declaration?;
-        let ast = decl.to_node(db);
-        Some(Source { file_id: decl.file_id(), ast })
-    }
-}
-
-impl HasSource for StructField {
-    type Ast = FieldSource;
-    fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<FieldSource> {
-        self.source_impl(db)
-    }
-}
-impl HasSource for Struct {
-    type Ast = TreeArc<ast::StructDef>;
-    fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<TreeArc<ast::StructDef>> {
-        self.id.source(db)
-    }
-}
-impl HasSource for Union {
-    type Ast = TreeArc<ast::StructDef>;
-    fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<TreeArc<ast::StructDef>> {
-        self.id.source(db)
-    }
-}
-impl HasSource for Enum {
-    type Ast = TreeArc<ast::EnumDef>;
-    fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<TreeArc<ast::EnumDef>> {
-        self.id.source(db)
-    }
-}
-impl HasSource for EnumVariant {
-    type Ast = TreeArc<ast::EnumVariant>;
-    fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<TreeArc<ast::EnumVariant>> {
-        self.source_impl(db)
-    }
-}
-impl HasSource for Function {
-    type Ast = TreeArc<ast::FnDef>;
-    fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<TreeArc<ast::FnDef>> {
-        self.id.source(db)
-    }
-}
-impl HasSource for Const {
-    type Ast = TreeArc<ast::ConstDef>;
-    fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<TreeArc<ast::ConstDef>> {
-        self.id.source(db)
-    }
-}
-impl HasSource for Static {
-    type Ast = TreeArc<ast::StaticDef>;
-    fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<TreeArc<ast::StaticDef>> {
-        self.id.source(db)
-    }
-}
-impl HasSource for Trait {
-    type Ast = TreeArc<ast::TraitDef>;
-    fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<TreeArc<ast::TraitDef>> {
-        self.id.source(db)
-    }
-}
-impl HasSource for TypeAlias {
-    type Ast = TreeArc<ast::TypeAliasDef>;
-    fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<TreeArc<ast::TypeAliasDef>> {
-        self.id.source(db)
-    }
-}
-impl HasSource for MacroDef {
-    type Ast = TreeArc<ast::MacroCall>;
-    fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<TreeArc<ast::MacroCall>> {
-        Source { file_id: self.id.0.file_id(), ast: self.id.0.to_node(db) }
-    }
-}
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index d2d6f95b73..d2a372f3bd 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -128,8 +128,8 @@ pub trait DefDatabase: SourceDatabase {
     #[salsa::invoke(crate::lang_item::LangItems::lang_item_query)]
     fn lang_item(&self, start_crate: Crate, item: SmolStr) -> Option<LangItemTarget>;
 
-    #[salsa::invoke(crate::code_model::docs::documentation_query)]
-    fn documentation(&self, def: crate::DocDef) -> Option<crate::Documentation>;
+    #[salsa::invoke(crate::docs::documentation_query)]
+    fn documentation(&self, def: crate::docs::DocDef) -> Option<crate::docs::Documentation>;
 }
 
 #[salsa::query_group(HirDatabaseStorage)]
diff --git a/crates/ra_hir/src/code_model/docs.rs b/crates/ra_hir/src/docs.rs
similarity index 72%
rename from crates/ra_hir/src/code_model/docs.rs
rename to crates/ra_hir/src/docs.rs
index da2b9b8547..1b0f84de52 100644
--- a/crates/ra_hir/src/code_model/docs.rs
+++ b/crates/ra_hir/src/docs.rs
@@ -3,7 +3,7 @@ use std::sync::Arc;
 use ra_syntax::ast;
 
 use crate::{
-    HirDatabase, DefDatabase, AstDatabase, HasSource,
+    HirDatabase, DefDatabase, AstDatabase,
     Module, StructField, Struct, Enum, EnumVariant, Static, Const, Function, Union, Trait, TypeAlias, FieldSource, MacroDef,
 };
 
@@ -71,21 +71,21 @@ pub(crate) fn documentation_query(
     def: DocDef,
 ) -> Option<Documentation> {
     match def {
-        DocDef::Module(it) => docs_from_ast(&*it.declaration_source(db)?.ast),
-        DocDef::StructField(it) => match it.source(db).ast {
+        DocDef::Module(it) => docs_from_ast(&*it.declaration_source(db)?.1),
+        DocDef::StructField(it) => match it.source(db).1 {
             FieldSource::Named(named) => docs_from_ast(&*named),
             FieldSource::Pos(..) => return None,
         },
-        DocDef::Struct(it) => docs_from_ast(&*it.source(db).ast),
-        DocDef::Enum(it) => docs_from_ast(&*it.source(db).ast),
-        DocDef::EnumVariant(it) => docs_from_ast(&*it.source(db).ast),
-        DocDef::Static(it) => docs_from_ast(&*it.source(db).ast),
-        DocDef::Const(it) => docs_from_ast(&*it.source(db).ast),
-        DocDef::Function(it) => docs_from_ast(&*it.source(db).ast),
-        DocDef::Union(it) => docs_from_ast(&*it.source(db).ast),
-        DocDef::Trait(it) => docs_from_ast(&*it.source(db).ast),
-        DocDef::TypeAlias(it) => docs_from_ast(&*it.source(db).ast),
-        DocDef::MacroDef(it) => docs_from_ast(&*it.source(db).ast),
+        DocDef::Struct(it) => docs_from_ast(&*it.source(db).1),
+        DocDef::Enum(it) => docs_from_ast(&*it.source(db).1),
+        DocDef::EnumVariant(it) => docs_from_ast(&*it.source(db).1),
+        DocDef::Static(it) => docs_from_ast(&*it.source(db).1),
+        DocDef::Const(it) => docs_from_ast(&*it.source(db).1),
+        DocDef::Function(it) => docs_from_ast(&*it.source(db).1),
+        DocDef::Union(it) => docs_from_ast(&*it.source(db).1),
+        DocDef::Trait(it) => docs_from_ast(&*it.source(db).1),
+        DocDef::TypeAlias(it) => docs_from_ast(&*it.source(db).1),
+        DocDef::MacroDef(it) => docs_from_ast(&*it.source(db).1),
     }
 }
 
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index b1973d19d4..012f374ec8 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -11,7 +11,6 @@ use ra_syntax::{
 
 use crate::{
     Path, Name, HirDatabase, Resolver,DefWithBody, Either, HirFileId, MacroCallLoc, MacroFileKind,
-    HasSource,
     name::AsName,
     type_ref::{Mutability, TypeRef},
 };
@@ -1019,19 +1018,19 @@ pub(crate) fn body_with_source_map_query(
 
     match def {
         DefWithBody::Const(ref c) => {
-            let src = c.source(db);
-            collector = ExprCollector::new(def, src.file_id, def.resolver(db), db);
-            collector.collect_const_body(&src.ast)
+            let (file_id, src) = c.source(db);
+            collector = ExprCollector::new(def, file_id, def.resolver(db), db);
+            collector.collect_const_body(&src)
         }
         DefWithBody::Function(ref f) => {
-            let src = f.source(db);
-            collector = ExprCollector::new(def, src.file_id, def.resolver(db), db);
-            collector.collect_fn_body(&src.ast)
+            let (file_id, src) = f.source(db);
+            collector = ExprCollector::new(def, file_id, def.resolver(db), db);
+            collector.collect_fn_body(&src)
         }
         DefWithBody::Static(ref s) => {
-            let src = s.source(db);
-            collector = ExprCollector::new(def, src.file_id, def.resolver(db), db);
-            collector.collect_static_body(&src.ast)
+            let (file_id, src) = s.source(db);
+            collector = ExprCollector::new(def, file_id, def.resolver(db), db);
+            collector.collect_static_body(&src)
         }
     }
 
diff --git a/crates/ra_hir/src/expr/validation.rs b/crates/ra_hir/src/expr/validation.rs
index 534fd482b4..a1b2641da1 100644
--- a/crates/ra_hir/src/expr/validation.rs
+++ b/crates/ra_hir/src/expr/validation.rs
@@ -5,7 +5,7 @@ use ra_syntax::ast::{AstNode, StructLit};
 
 use crate::{
     expr::AstPtr,
-    HirDatabase, Function, Name, HasSource,
+    HirDatabase, Function, Name,
     diagnostics::{DiagnosticSink, MissingFields},
     adt::AdtDef,
     Path,
@@ -71,7 +71,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
             return;
         }
         let source_map = self.func.body_source_map(db);
-        let file_id = self.func.source(db).file_id;
+        let file_id = self.func.source(db).0;
         let source_file = db.parse(file_id.original_file(db)).tree;
         if let Some(field_list_node) = source_map
             .expr_syntax(id)
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs
index 462b136b7f..b6c5e18d3c 100644
--- a/crates/ra_hir/src/generics.rs
+++ b/crates/ra_hir/src/generics.rs
@@ -8,10 +8,8 @@ use std::sync::Arc;
 use ra_syntax::ast::{self, NameOwner, TypeParamsOwner, TypeBoundsOwner, DefaultTypeParamOwner};
 
 use crate::{
-    HasSource,
-    Name, AsName, Function, Struct, Union, Enum, Trait, TypeAlias, ImplBlock, Container, AdtDef,
     db::{HirDatabase, DefDatabase, AstDatabase},
-    path::Path, type_ref::TypeRef,
+    Name, AsName, Function, Struct, Union, Enum, Trait, TypeAlias, ImplBlock, Container, path::Path, type_ref::TypeRef, AdtDef
 };
 
 /// Data about a generic parameter (to a function, struct, impl, ...).
@@ -70,10 +68,10 @@ impl GenericParams {
         generics.parent_params = parent.map(|p| db.generic_params(p));
         let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32;
         match def {
-            GenericDef::Function(it) => generics.fill(&*it.source(db).ast, start),
-            GenericDef::Struct(it) => generics.fill(&*it.source(db).ast, start),
-            GenericDef::Union(it) => generics.fill(&*it.source(db).ast, start),
-            GenericDef::Enum(it) => generics.fill(&*it.source(db).ast, start),
+            GenericDef::Function(it) => generics.fill(&*it.source(db).1, start),
+            GenericDef::Struct(it) => generics.fill(&*it.source(db).1, start),
+            GenericDef::Union(it) => generics.fill(&*it.source(db).1, start),
+            GenericDef::Enum(it) => generics.fill(&*it.source(db).1, start),
             GenericDef::Trait(it) => {
                 // traits get the Self type as an implicit first type parameter
                 generics.params.push(GenericParam {
@@ -81,10 +79,10 @@ impl GenericParams {
                     name: Name::self_type(),
                     default: None,
                 });
-                generics.fill(&*it.source(db).ast, start + 1);
+                generics.fill(&*it.source(db).1, start + 1);
             }
-            GenericDef::TypeAlias(it) => generics.fill(&*it.source(db).ast, start),
-            GenericDef::ImplBlock(it) => generics.fill(&*it.source(db).ast, start),
+            GenericDef::TypeAlias(it) => generics.fill(&*it.source(db).1, start),
+            GenericDef::ImplBlock(it) => generics.fill(&*it.source(db).1, start),
         }
 
         Arc::new(generics)
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs
index 352f9ffd93..a955618121 100644
--- a/crates/ra_hir/src/ids.rs
+++ b/crates/ra_hir/src/ids.rs
@@ -9,7 +9,7 @@ use ra_prof::profile;
 use mbe::MacroRules;
 
 use crate::{
-    Module, DefDatabase, AstId, FileAstId, AstDatabase, Source,
+    Module, DefDatabase, AstId, FileAstId, AstDatabase,
 };
 
 /// hir makes heavy use of ids: integer (u32) handlers to various things. You
@@ -265,10 +265,10 @@ pub(crate) trait AstItemDef<N: AstNode>: salsa::InternKey + Clone {
         let loc = ItemLoc { module: ctx.module, ast_id: ast_id.with_file_id(ctx.file_id) };
         Self::intern(ctx.db, loc)
     }
-    fn source(self, db: &(impl AstDatabase + DefDatabase)) -> Source<TreeArc<N>> {
+    fn source(self, db: &(impl AstDatabase + DefDatabase)) -> (HirFileId, TreeArc<N>) {
         let loc = self.lookup_intern(db);
         let ast = loc.ast_id.to_node(db);
-        Source { file_id: loc.ast_id.file_id(), ast }
+        (loc.ast_id.file_id(), ast)
     }
     fn module(self, db: &impl DefDatabase) -> Module {
         let loc = self.lookup_intern(db);
diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs
index fb9daf1bf9..a0d3b33fe6 100644
--- a/crates/ra_hir/src/impl_block.rs
+++ b/crates/ra_hir/src/impl_block.rs
@@ -8,7 +8,7 @@ use ra_syntax::{
 };
 
 use crate::{
-    Const, TypeAlias, Function, HirFileId, AstDatabase, HasSource, Source,
+    Const, TypeAlias, Function, HirFileId, AstDatabase,
     HirDatabase, DefDatabase, TraitRef,
     type_ref::TypeRef,
     ids::LocationCtx,
@@ -44,15 +44,6 @@ pub struct ImplBlock {
     impl_id: ImplId,
 }
 
-impl HasSource for ImplBlock {
-    type Ast = TreeArc<ast::ImplBlock>;
-    fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<TreeArc<ast::ImplBlock>> {
-        let source_map = db.impls_in_module_with_source_map(self.module).1;
-        let src = self.module.definition_source(db);
-        Source { file_id: src.file_id, ast: source_map.get(&src.ast, self.impl_id) }
-    }
-}
-
 impl ImplBlock {
     pub(crate) fn containing(
         module_impl_blocks: Arc<ModuleImplBlocks>,
@@ -66,6 +57,16 @@ impl ImplBlock {
         ImplBlock { module, impl_id }
     }
 
+    /// Returns the syntax of the impl block
+    pub fn source(
+        &self,
+        db: &(impl DefDatabase + AstDatabase),
+    ) -> (HirFileId, TreeArc<ast::ImplBlock>) {
+        let source_map = db.impls_in_module_with_source_map(self.module).1;
+        let (file_id, source) = self.module.definition_source(db);
+        (file_id, source_map.get(&source, self.impl_id))
+    }
+
     pub fn id(&self) -> ImplId {
         self.impl_id
     }
@@ -200,8 +201,8 @@ impl ModuleImplBlocks {
             impls_by_def: FxHashMap::default(),
         };
 
-        let src = m.module.definition_source(db);
-        let node = match &src.ast {
+        let (file_id, module_source) = m.module.definition_source(db);
+        let node = match &module_source {
             ModuleSource::SourceFile(node) => node.syntax(),
             ModuleSource::Module(node) => {
                 node.item_list().expect("inline module should have item list").syntax()
@@ -209,7 +210,7 @@ impl ModuleImplBlocks {
         };
 
         for impl_block_ast in node.children().filter_map(ast::ImplBlock::cast) {
-            let impl_block = ImplData::from_ast(db, src.file_id, m.module, impl_block_ast);
+            let impl_block = ImplData::from_ast(db, file_id, m.module, impl_block_ast);
             let id = m.impls.alloc(impl_block);
             for &impl_item in &m.impls[id].items {
                 m.impls_by_def.insert(impl_item, id);
diff --git a/crates/ra_hir/src/lang_item.rs b/crates/ra_hir/src/lang_item.rs
index cdc9182d6b..684fbc0685 100644
--- a/crates/ra_hir/src/lang_item.rs
+++ b/crates/ra_hir/src/lang_item.rs
@@ -84,7 +84,7 @@ impl LangItems {
     ) {
         // Look for impl targets
         let (impl_blocks, source_map) = db.impls_in_module_with_source_map(module.clone());
-        let source = module.definition_source(db).ast;
+        let source = module.definition_source(db).1;
         for (impl_id, _) in impl_blocks.impls.iter() {
             let impl_block = source_map.get(&source, impl_id);
             let lang_item_name = impl_block
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 2e99bdac83..0e4aaf678e 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -38,6 +38,7 @@ mod impl_block;
 mod expr;
 mod lang_item;
 mod generics;
+mod docs;
 mod resolve;
 pub mod diagnostics;
 
@@ -63,6 +64,7 @@ pub use self::{
     nameres::{PerNs, Namespace, ImportId},
     ty::{Ty, ApplicationTy, TypeCtor, TraitRef, Substs, display::HirDisplay, CallableDef},
     impl_block::{ImplBlock, ImplItem},
+    docs::{Docs, Documentation},
     adt::AdtDef,
     expr::ExprScopes,
     resolve::Resolution,
@@ -80,6 +82,4 @@ pub use self::code_model::{
     Static, Const, ConstSignature,
     Trait, TypeAlias, MacroDef, Container,
     BuiltinType,
-    src::{Source, HasSource},
-    docs::{Docs, Documentation, DocDef},
 };
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 4f9e8c5a9e..876ebe0e34 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -97,13 +97,13 @@ pub fn struct_from_module(
     module: Module,
     struct_def: &ast::StructDef,
 ) -> Struct {
-    let file_id = module.definition_source(db).file_id;
+    let (file_id, _) = module.definition_source(db);
     let ctx = LocationCtx::new(db, module, file_id);
     Struct { id: ctx.to_def(struct_def) }
 }
 
 pub fn enum_from_module(db: &impl HirDatabase, module: Module, enum_def: &ast::EnumDef) -> Enum {
-    let file_id = module.definition_source(db).file_id;
+    let (file_id, _) = module.definition_source(db);
     let ctx = LocationCtx::new(db, module, file_id);
     Enum { id: ctx.to_def(enum_def) }
 }
@@ -113,7 +113,7 @@ pub fn trait_from_module(
     module: Module,
     trait_def: &ast::TraitDef,
 ) -> Trait {
-    let file_id = module.definition_source(db).file_id;
+    let (file_id, _) = module.definition_source(db);
     let ctx = LocationCtx::new(db, module, file_id);
     Trait { id: ctx.to_def(trait_def) }
 }
diff --git a/crates/ra_hir/src/traits.rs b/crates/ra_hir/src/traits.rs
index f2950e1b29..967654e97e 100644
--- a/crates/ra_hir/src/traits.rs
+++ b/crates/ra_hir/src/traits.rs
@@ -6,7 +6,7 @@ use rustc_hash::FxHashMap;
 use ra_syntax::ast::{self, NameOwner};
 
 use crate::{
-    Function, Const, TypeAlias, Name, DefDatabase, Trait, AstDatabase, Module, HasSource,
+    Function, Const, TypeAlias, Name, DefDatabase, Trait, AstDatabase, Module,
     ids::LocationCtx, name::AsName,
 };
 
@@ -22,12 +22,12 @@ impl TraitData {
         db: &(impl DefDatabase + AstDatabase),
         tr: Trait,
     ) -> Arc<TraitData> {
-        let src = tr.source(db);
-        let name = src.ast.name().map(|n| n.as_name());
+        let (file_id, node) = tr.source(db);
+        let name = node.name().map(|n| n.as_name());
         let module = tr.module(db);
-        let ctx = LocationCtx::new(db, module, src.file_id);
-        let auto = src.ast.is_auto();
-        let items = if let Some(item_list) = src.ast.item_list() {
+        let ctx = LocationCtx::new(db, module, file_id);
+        let auto = node.is_auto();
+        let items = if let Some(item_list) = node.item_list() {
             item_list
                 .impl_items()
                 .map(|item_node| match item_node.kind() {
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index fef0f1d244..6aa727ea10 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -1415,7 +1415,7 @@ mod diagnostics {
     use crate::{
         expr::ExprId,
         diagnostics::{DiagnosticSink, NoSuchField},
-        HirDatabase, Function, HasSource,
+        HirDatabase, Function,
 };
 
     #[derive(Debug, PartialEq, Eq, Clone)]
@@ -1432,7 +1432,7 @@ mod diagnostics {
         ) {
             match self {
                 InferenceDiagnostic::NoSuchField { expr, field } => {
-                    let file = owner.source(db).file_id;
+                    let (file, _) = owner.source(db);
                     let field = owner.body_source_map(db).field_syntax(*expr, *field);
                     sink.push(NoSuchField { file, field })
                 }
diff --git a/crates/ra_hir/src/type_alias.rs b/crates/ra_hir/src/type_alias.rs
index 87b9caa8aa..970468e3cb 100644
--- a/crates/ra_hir/src/type_alias.rs
+++ b/crates/ra_hir/src/type_alias.rs
@@ -2,12 +2,12 @@
 
 use std::sync::Arc;
 
-use crate::{TypeAlias, DefDatabase, AstDatabase, HasSource, type_ref::TypeRef};
+use crate::{TypeAlias, DefDatabase, AstDatabase, type_ref::TypeRef};
 
 pub(crate) fn type_alias_ref_query(
     db: &(impl DefDatabase + AstDatabase),
     typ: TypeAlias,
 ) -> Arc<TypeRef> {
-    let node = typ.source(db).ast;
+    let (_, node) = typ.source(db);
     Arc::new(TypeRef::from_ast_opt(node.type_ref()))
 }
diff --git a/crates/ra_ide_api/src/change.rs b/crates/ra_ide_api/src/change.rs
index ce03a0f952..247dc0feed 100644
--- a/crates/ra_ide_api/src/change.rs
+++ b/crates/ra_ide_api/src/change.rs
@@ -225,6 +225,7 @@ impl RootDatabase {
         let sweep = SweepStrategy::default().discard_values().sweep_all_revisions();
 
         self.query(ra_db::ParseQuery).sweep(sweep);
+
         self.query(hir::db::ParseMacroQuery).sweep(sweep);
         self.query(hir::db::MacroDefQuery).sweep(sweep);
         self.query(hir::db::MacroArgQuery).sweep(sweep);
diff --git a/crates/ra_ide_api/src/completion/presentation.rs b/crates/ra_ide_api/src/completion/presentation.rs
index f4ff4404b1..d405161d63 100644
--- a/crates/ra_ide_api/src/completion/presentation.rs
+++ b/crates/ra_ide_api/src/completion/presentation.rs
@@ -1,7 +1,7 @@
 //! This modules takes care of rendering various defenitions as completion items.
 use join_to_string::join;
 use test_utils::tested_by;
-use hir::{Docs, PerNs, Resolution, HirDisplay, HasSource};
+use hir::{Docs, PerNs, Resolution, HirDisplay};
 use ra_syntax::ast::NameOwner;
 
 use crate::completion::{
@@ -100,7 +100,7 @@ impl Completions {
     ) {
         let sig = func.signature(ctx.db);
         let name = name.unwrap_or_else(|| sig.name().to_string());
-        let ast_node = func.source(ctx.db).ast;
+        let (_, ast_node) = func.source(ctx.db);
         let detail = function_label(&ast_node);
 
         let mut builder = CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name)
@@ -126,11 +126,12 @@ impl Completions {
     }
 
     pub(crate) fn add_const(&mut self, ctx: &CompletionContext, constant: hir::Const) {
-        let ast_node = constant.source(ctx.db).ast;
+        let (_file_id, ast_node) = constant.source(ctx.db);
         let name = match ast_node.name() {
             Some(name) => name,
             _ => return,
         };
+        let (_, ast_node) = constant.source(ctx.db);
         let detail = const_label(&ast_node);
 
         CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.text().to_string())
@@ -141,12 +142,13 @@ impl Completions {
     }
 
     pub(crate) fn add_type_alias(&mut self, ctx: &CompletionContext, type_alias: hir::TypeAlias) {
-        let type_def = type_alias.source(ctx.db).ast;
+        let (_file_id, type_def) = type_alias.source(ctx.db);
         let name = match type_def.name() {
             Some(name) => name,
             _ => return,
         };
-        let detail = type_label(&type_def);
+        let (_, ast_node) = type_alias.source(ctx.db);
+        let detail = type_label(&ast_node);
 
         CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.text().to_string())
             .kind(CompletionItemKind::TypeAlias)
diff --git a/crates/ra_ide_api/src/db.rs b/crates/ra_ide_api/src/db.rs
index b3f395502e..d1a452ecb5 100644
--- a/crates/ra_ide_api/src/db.rs
+++ b/crates/ra_ide_api/src/db.rs
@@ -5,7 +5,7 @@ use std::{
 
 use ra_db::{
     CheckCanceled, FileId, Canceled, SourceDatabase,
-    salsa::{self, Database},
+    salsa,
 };
 
 use crate::{LineIndex, symbol_index::{self, SymbolsDatabase}};
@@ -41,12 +41,6 @@ impl salsa::Database for RootDatabase {
 
 impl Default for RootDatabase {
     fn default() -> RootDatabase {
-        RootDatabase::new(None)
-    }
-}
-
-impl RootDatabase {
-    pub fn new(lru_capacity: Option<usize>) -> RootDatabase {
         let mut db = RootDatabase {
             runtime: salsa::Runtime::default(),
             last_gc: time::Instant::now(),
@@ -55,9 +49,6 @@ impl RootDatabase {
         db.set_crate_graph(Default::default());
         db.set_local_roots(Default::default());
         db.set_library_roots(Default::default());
-        let lru_capacity = lru_capacity.unwrap_or(ra_db::DEFAULT_LRU_CAP);
-        db.query_mut(ra_db::ParseQuery).set_lru_capacity(lru_capacity);
-        db.query_mut(hir::db::ParseMacroQuery).set_lru_capacity(lru_capacity);
         db
     }
 }
diff --git a/crates/ra_ide_api/src/display/function_signature.rs b/crates/ra_ide_api/src/display/function_signature.rs
index b0b0c71227..d09950bce0 100644
--- a/crates/ra_ide_api/src/display/function_signature.rs
+++ b/crates/ra_ide_api/src/display/function_signature.rs
@@ -1,11 +1,10 @@
+use super::{where_predicates, generic_parameters};
+use crate::db;
 use std::fmt::{self, Display};
-
 use join_to_string::join;
 use ra_syntax::ast::{self, AstNode, NameOwner, VisibilityOwner};
 use std::convert::From;
-use hir::{Docs, Documentation, HasSource};
-
-use crate::{db, display::{where_predicates, generic_parameters}};
+use hir::{Docs, Documentation};
 
 /// Contains information about a function signature
 #[derive(Debug)]
@@ -34,7 +33,7 @@ impl FunctionSignature {
 
     pub(crate) fn from_hir(db: &db::RootDatabase, function: hir::Function) -> Self {
         let doc = function.docs(db);
-        let ast_node = function.source(db).ast;
+        let (_, ast_node) = function.source(db);
         FunctionSignature::from(&*ast_node).with_doc_opt(doc)
     }
 }
diff --git a/crates/ra_ide_api/src/display/navigation_target.rs b/crates/ra_ide_api/src/display/navigation_target.rs
index 823cdaaf3c..cfd3f54787 100644
--- a/crates/ra_ide_api/src/display/navigation_target.rs
+++ b/crates/ra_ide_api/src/display/navigation_target.rs
@@ -1,11 +1,11 @@
 use ra_db::{FileId, SourceDatabase};
 use ra_syntax::{
-    SyntaxNode, AstNode, SmolStr, TextRange, AstPtr, TreeArc,
+    SyntaxNode, AstNode, SmolStr, TextRange, AstPtr,
     SyntaxKind::{self, NAME},
     ast::{self, DocCommentsOwner},
     algo::visit::{visitor, Visitor},
 };
-use hir::{ModuleSource, FieldSource, ImplItem, HasSource};
+use hir::{ModuleSource, FieldSource, ImplItem};
 
 use crate::{FileSymbol, db::RootDatabase};
 use super::short_label::ShortLabel;
@@ -129,10 +129,10 @@ impl NavigationTarget {
     }
 
     pub(crate) fn from_module(db: &RootDatabase, module: hir::Module) -> NavigationTarget {
-        let src = module.definition_source(db);
-        let file_id = src.file_id.as_original_file();
+        let (file_id, source) = module.definition_source(db);
+        let file_id = file_id.as_original_file();
         let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default();
-        match src.ast {
+        match source {
             ModuleSource::SourceFile(node) => {
                 NavigationTarget::from_syntax(file_id, name, None, node.syntax(), None, None)
             }
@@ -149,24 +149,34 @@ impl NavigationTarget {
 
     pub(crate) fn from_module_to_decl(db: &RootDatabase, module: hir::Module) -> NavigationTarget {
         let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default();
-        if let Some(src) = module.declaration_source(db) {
-            let file_id = src.file_id.as_original_file();
+        if let Some((file_id, source)) = module.declaration_source(db) {
+            let file_id = file_id.as_original_file();
             return NavigationTarget::from_syntax(
                 file_id,
                 name,
                 None,
-                src.ast.syntax(),
-                src.ast.doc_comment_text(),
-                src.ast.short_label(),
+                source.syntax(),
+                source.doc_comment_text(),
+                source.short_label(),
             );
         }
         NavigationTarget::from_module(db, module)
     }
 
+    pub(crate) fn from_function(db: &RootDatabase, func: hir::Function) -> NavigationTarget {
+        let (file_id, fn_def) = func.source(db);
+        NavigationTarget::from_named(
+            file_id.original_file(db),
+            &*fn_def,
+            fn_def.doc_comment_text(),
+            fn_def.short_label(),
+        )
+    }
+
     pub(crate) fn from_field(db: &RootDatabase, field: hir::StructField) -> NavigationTarget {
-        let src = field.source(db);
-        let file_id = src.file_id.original_file(db);
-        match src.ast {
+        let (file_id, field) = field.source(db);
+        let file_id = file_id.original_file(db);
+        match field {
             FieldSource::Named(it) => {
                 NavigationTarget::from_named(file_id, &*it, it.doc_comment_text(), it.short_label())
             }
@@ -176,25 +186,35 @@ impl NavigationTarget {
         }
     }
 
-    pub(crate) fn from_def_source<A, D>(db: &RootDatabase, def: D) -> NavigationTarget
-    where
-        D: HasSource<Ast = TreeArc<A>>,
-        A: ast::DocCommentsOwner + ast::NameOwner + ShortLabel,
-    {
-        let src = def.source(db);
-        NavigationTarget::from_named(
-            src.file_id.original_file(db),
-            &*src.ast,
-            src.ast.doc_comment_text(),
-            src.ast.short_label(),
-        )
-    }
-
     pub(crate) fn from_adt_def(db: &RootDatabase, adt_def: hir::AdtDef) -> NavigationTarget {
         match adt_def {
-            hir::AdtDef::Struct(it) => NavigationTarget::from_def_source(db, it),
-            hir::AdtDef::Union(it) => NavigationTarget::from_def_source(db, it),
-            hir::AdtDef::Enum(it) => NavigationTarget::from_def_source(db, it),
+            hir::AdtDef::Struct(s) => {
+                let (file_id, node) = s.source(db);
+                NavigationTarget::from_named(
+                    file_id.original_file(db),
+                    &*node,
+                    node.doc_comment_text(),
+                    node.short_label(),
+                )
+            }
+            hir::AdtDef::Union(s) => {
+                let (file_id, node) = s.source(db);
+                NavigationTarget::from_named(
+                    file_id.original_file(db),
+                    &*node,
+                    node.doc_comment_text(),
+                    node.short_label(),
+                )
+            }
+            hir::AdtDef::Enum(s) => {
+                let (file_id, node) = s.source(db);
+                NavigationTarget::from_named(
+                    file_id.original_file(db),
+                    &*node,
+                    node.doc_comment_text(),
+                    node.short_label(),
+                )
+            }
         }
     }
 
@@ -204,15 +224,79 @@ impl NavigationTarget {
     ) -> Option<NavigationTarget> {
         let nav = match module_def {
             hir::ModuleDef::Module(module) => NavigationTarget::from_module(db, module),
-            hir::ModuleDef::Function(func) => NavigationTarget::from_def_source(db, func),
-            hir::ModuleDef::Struct(it) => NavigationTarget::from_adt_def(db, it.into()),
-            hir::ModuleDef::Enum(it) => NavigationTarget::from_adt_def(db, it.into()),
-            hir::ModuleDef::Union(it) => NavigationTarget::from_adt_def(db, it.into()),
-            hir::ModuleDef::Const(it) => NavigationTarget::from_def_source(db, it),
-            hir::ModuleDef::Static(it) => NavigationTarget::from_def_source(db, it),
-            hir::ModuleDef::EnumVariant(it) => NavigationTarget::from_def_source(db, it),
-            hir::ModuleDef::Trait(it) => NavigationTarget::from_def_source(db, it),
-            hir::ModuleDef::TypeAlias(it) => NavigationTarget::from_def_source(db, it),
+            hir::ModuleDef::Function(func) => NavigationTarget::from_function(db, func),
+            hir::ModuleDef::Struct(s) => {
+                let (file_id, node) = s.source(db);
+                NavigationTarget::from_named(
+                    file_id.original_file(db),
+                    &*node,
+                    node.doc_comment_text(),
+                    node.short_label(),
+                )
+            }
+            hir::ModuleDef::Union(s) => {
+                let (file_id, node) = s.source(db);
+                NavigationTarget::from_named(
+                    file_id.original_file(db),
+                    &*node,
+                    node.doc_comment_text(),
+                    node.short_label(),
+                )
+            }
+            hir::ModuleDef::Const(s) => {
+                let (file_id, node) = s.source(db);
+                NavigationTarget::from_named(
+                    file_id.original_file(db),
+                    &*node,
+                    node.doc_comment_text(),
+                    node.short_label(),
+                )
+            }
+            hir::ModuleDef::Static(s) => {
+                let (file_id, node) = s.source(db);
+                NavigationTarget::from_named(
+                    file_id.original_file(db),
+                    &*node,
+                    node.doc_comment_text(),
+                    node.short_label(),
+                )
+            }
+            hir::ModuleDef::Enum(e) => {
+                let (file_id, node) = e.source(db);
+                NavigationTarget::from_named(
+                    file_id.original_file(db),
+                    &*node,
+                    node.doc_comment_text(),
+                    node.short_label(),
+                )
+            }
+            hir::ModuleDef::EnumVariant(var) => {
+                let (file_id, node) = var.source(db);
+                NavigationTarget::from_named(
+                    file_id.original_file(db),
+                    &*node,
+                    node.doc_comment_text(),
+                    node.short_label(),
+                )
+            }
+            hir::ModuleDef::Trait(e) => {
+                let (file_id, node) = e.source(db);
+                NavigationTarget::from_named(
+                    file_id.original_file(db),
+                    &*node,
+                    node.doc_comment_text(),
+                    node.short_label(),
+                )
+            }
+            hir::ModuleDef::TypeAlias(e) => {
+                let (file_id, node) = e.source(db);
+                NavigationTarget::from_named(
+                    file_id.original_file(db),
+                    &*node,
+                    node.doc_comment_text(),
+                    node.short_label(),
+                )
+            }
             hir::ModuleDef::BuiltinType(..) => {
                 return None;
             }
@@ -224,12 +308,12 @@ impl NavigationTarget {
         db: &RootDatabase,
         impl_block: hir::ImplBlock,
     ) -> NavigationTarget {
-        let src = impl_block.source(db);
+        let (file_id, node) = impl_block.source(db);
         NavigationTarget::from_syntax(
-            src.file_id.as_original_file(),
+            file_id.as_original_file(),
             "impl".into(),
             None,
-            src.ast.syntax(),
+            node.syntax(),
             None,
             None,
         )
@@ -237,19 +321,35 @@ impl NavigationTarget {
 
     pub(crate) fn from_impl_item(db: &RootDatabase, impl_item: hir::ImplItem) -> NavigationTarget {
         match impl_item {
-            ImplItem::Method(it) => NavigationTarget::from_def_source(db, it),
-            ImplItem::Const(it) => NavigationTarget::from_def_source(db, it),
-            ImplItem::TypeAlias(it) => NavigationTarget::from_def_source(db, it),
+            ImplItem::Method(f) => NavigationTarget::from_function(db, f),
+            ImplItem::Const(c) => {
+                let (file_id, node) = c.source(db);
+                NavigationTarget::from_named(
+                    file_id.original_file(db),
+                    &*node,
+                    node.doc_comment_text(),
+                    node.short_label(),
+                )
+            }
+            ImplItem::TypeAlias(a) => {
+                let (file_id, node) = a.source(db);
+                NavigationTarget::from_named(
+                    file_id.original_file(db),
+                    &*node,
+                    node.doc_comment_text(),
+                    node.short_label(),
+                )
+            }
         }
     }
 
     pub(crate) fn from_macro_def(db: &RootDatabase, macro_call: hir::MacroDef) -> NavigationTarget {
-        let src = macro_call.source(db);
-        log::debug!("nav target {}", src.ast.syntax().debug_dump());
+        let (file_id, node) = macro_call.source(db);
+        log::debug!("nav target {}", node.syntax().debug_dump());
         NavigationTarget::from_named(
-            src.file_id.original_file(db),
-            &*src.ast,
-            src.ast.doc_comment_text(),
+            file_id.original_file(db),
+            &*node,
+            node.doc_comment_text(),
             None,
         )
     }
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs
index 63ba6cf9d3..325a5a4f3b 100644
--- a/crates/ra_ide_api/src/goto_definition.rs
+++ b/crates/ra_ide_api/src/goto_definition.rs
@@ -59,10 +59,10 @@ pub(crate) fn reference_definition(
     let analyzer = hir::SourceAnalyzer::new(db, file_id, name_ref.syntax(), None);
 
     match classify_name_ref(db, &analyzer, name_ref) {
+        Some(Method(func)) => return Exact(NavigationTarget::from_function(db, func)),
         Some(Macro(mac)) => return Exact(NavigationTarget::from_macro_def(db, mac)),
         Some(FieldAccess(field)) => return Exact(NavigationTarget::from_field(db, field)),
         Some(AssocItem(assoc)) => return Exact(NavigationTarget::from_impl_item(db, assoc)),
-        Some(Method(func)) => return Exact(NavigationTarget::from_def_source(db, func)),
         Some(Def(def)) => match NavigationTarget::from_def(db, def) {
             Some(nav) => return Exact(nav),
             None => return Approximate(vec![]),
@@ -253,12 +253,12 @@ mod tests {
             //- /foo/lib.rs
             #[macro_export]
             macro_rules! foo {
-                () => {
+                () => {             
                     {}
                 };
-            }
+            }            
             ",
-            "foo MACRO_CALL FileId(2) [0; 66) [29; 32)",
+            "foo MACRO_CALL FileId(2) [0; 79) [29; 32)",
         );
     }
 
diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs
index df877c324c..fbabeb194e 100644
--- a/crates/ra_ide_api/src/hover.rs
+++ b/crates/ra_ide_api/src/hover.rs
@@ -1,10 +1,9 @@
 use ra_db::SourceDatabase;
 use ra_syntax::{
-    AstNode, TreeArc,
-    ast::{self, DocCommentsOwner},
+    AstNode, ast::{self, DocCommentsOwner},
     algo::{find_covering_element, find_node_at_offset, ancestors_at_offset, visit::{visitor, Visitor}},
 };
-use hir::{HirDisplay, HasSource};
+use hir::HirDisplay;
 
 use crate::{
     db::RootDatabase,
@@ -95,41 +94,79 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
     if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(file.syntax(), position.offset) {
         let analyzer = hir::SourceAnalyzer::new(db, position.file_id, name_ref.syntax(), None);
 
-        let mut no_fallback = false;
-
         match classify_name_ref(db, &analyzer, name_ref) {
-            Some(Method(it)) => res.extend(from_def_source(db, it)),
+            Some(Method(it)) => {
+                let it = it.source(db).1;
+                res.extend(hover_text(it.doc_comment_text(), it.short_label()));
+            }
             Some(Macro(it)) => {
-                let src = it.source(db);
-                res.extend(hover_text(src.ast.doc_comment_text(), None));
+                let it = it.source(db).1;
+                res.extend(hover_text(it.doc_comment_text(), None));
             }
             Some(FieldAccess(it)) => {
-                let src = it.source(db);
-                if let hir::FieldSource::Named(it) = src.ast {
+                let it = it.source(db).1;
+                if let hir::FieldSource::Named(it) = it {
                     res.extend(hover_text(it.doc_comment_text(), it.short_label()));
                 }
             }
-            Some(AssocItem(it)) => res.extend(match it {
-                hir::ImplItem::Method(it) => from_def_source(db, it),
-                hir::ImplItem::Const(it) => from_def_source(db, it),
-                hir::ImplItem::TypeAlias(it) => from_def_source(db, it),
-            }),
+            Some(AssocItem(it)) => match it {
+                hir::ImplItem::Method(it) => {
+                    let it = it.source(db).1;
+                    res.extend(hover_text(it.doc_comment_text(), it.short_label()))
+                }
+                hir::ImplItem::Const(it) => {
+                    let it = it.source(db).1;
+                    res.extend(hover_text(it.doc_comment_text(), it.short_label()))
+                }
+                hir::ImplItem::TypeAlias(it) => {
+                    let it = it.source(db).1;
+                    res.extend(hover_text(it.doc_comment_text(), it.short_label()))
+                }
+            },
             Some(Def(it)) => {
                 match it {
                     hir::ModuleDef::Module(it) => {
-                        if let hir::ModuleSource::Module(it) = it.definition_source(db).ast {
+                        let it = it.definition_source(db).1;
+                        if let hir::ModuleSource::Module(it) = it {
                             res.extend(hover_text(it.doc_comment_text(), it.short_label()))
                         }
                     }
-                    hir::ModuleDef::Function(it) => res.extend(from_def_source(db, it)),
-                    hir::ModuleDef::Struct(it) => res.extend(from_def_source(db, it)),
-                    hir::ModuleDef::Union(it) => res.extend(from_def_source(db, it)),
-                    hir::ModuleDef::Enum(it) => res.extend(from_def_source(db, it)),
-                    hir::ModuleDef::EnumVariant(it) => res.extend(from_def_source(db, it)),
-                    hir::ModuleDef::Const(it) => res.extend(from_def_source(db, it)),
-                    hir::ModuleDef::Static(it) => res.extend(from_def_source(db, it)),
-                    hir::ModuleDef::Trait(it) => res.extend(from_def_source(db, it)),
-                    hir::ModuleDef::TypeAlias(it) => res.extend(from_def_source(db, it)),
+                    hir::ModuleDef::Function(it) => {
+                        let it = it.source(db).1;
+                        res.extend(hover_text(it.doc_comment_text(), it.short_label()))
+                    }
+                    hir::ModuleDef::Struct(it) => {
+                        let it = it.source(db).1;
+                        res.extend(hover_text(it.doc_comment_text(), it.short_label()))
+                    }
+                    hir::ModuleDef::Union(it) => {
+                        let it = it.source(db).1;
+                        res.extend(hover_text(it.doc_comment_text(), it.short_label()))
+                    }
+                    hir::ModuleDef::Enum(it) => {
+                        let it = it.source(db).1;
+                        res.extend(hover_text(it.doc_comment_text(), it.short_label()))
+                    }
+                    hir::ModuleDef::EnumVariant(it) => {
+                        let it = it.source(db).1;
+                        res.extend(hover_text(it.doc_comment_text(), it.short_label()))
+                    }
+                    hir::ModuleDef::Const(it) => {
+                        let it = it.source(db).1;
+                        res.extend(hover_text(it.doc_comment_text(), it.short_label()))
+                    }
+                    hir::ModuleDef::Static(it) => {
+                        let it = it.source(db).1;
+                        res.extend(hover_text(it.doc_comment_text(), it.short_label()))
+                    }
+                    hir::ModuleDef::Trait(it) => {
+                        let it = it.source(db).1;
+                        res.extend(hover_text(it.doc_comment_text(), it.short_label()))
+                    }
+                    hir::ModuleDef::TypeAlias(it) => {
+                        let it = it.source(db).1;
+                        res.extend(hover_text(it.doc_comment_text(), it.short_label()))
+                    }
                     hir::ModuleDef::BuiltinType(_) => {
                         // FIXME: hover for builtin Type ?
                     }
@@ -137,16 +174,27 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
             }
             Some(SelfType(ty)) => {
                 if let Some((adt_def, _)) = ty.as_adt() {
-                    res.extend(match adt_def {
-                        hir::AdtDef::Struct(it) => from_def_source(db, it),
-                        hir::AdtDef::Union(it) => from_def_source(db, it),
-                        hir::AdtDef::Enum(it) => from_def_source(db, it),
-                    })
+                    match adt_def {
+                        hir::AdtDef::Struct(it) => {
+                            let it = it.source(db).1;
+                            res.extend(hover_text(it.doc_comment_text(), it.short_label()))
+                        }
+                        hir::AdtDef::Union(it) => {
+                            let it = it.source(db).1;
+                            res.extend(hover_text(it.doc_comment_text(), it.short_label()))
+                        }
+                        hir::AdtDef::Enum(it) => {
+                            let it = it.source(db).1;
+                            res.extend(hover_text(it.doc_comment_text(), it.short_label()))
+                        }
+                    }
                 }
             }
-            Some(Pat(_)) | Some(SelfParam(_)) => {
-                // Hover for these shows type names
-                no_fallback = true;
+            Some(Pat(_)) => {
+                res.extend(None);
+            }
+            Some(SelfParam(_)) => {
+                res.extend(None);
             }
             Some(GenericParam(_)) => {
                 // FIXME: Hover for generic param
@@ -154,7 +202,7 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
             None => {}
         }
 
-        if res.is_empty() && !no_fallback {
+        if res.is_empty() {
             // Fallback index based approach:
             let symbols = crate::symbol_index::index_resolve(db, name_ref);
             for sym in symbols {
@@ -222,16 +270,7 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
         return None;
     }
     let res = RangeInfo::new(range, res);
-    return Some(res);
-
-    fn from_def_source<A, D>(db: &RootDatabase, def: D) -> Option<String>
-    where
-        D: HasSource<Ast = TreeArc<A>>,
-        A: ast::DocCommentsOwner + ast::NameOwner + ShortLabel,
-    {
-        let src = def.source(db);
-        hover_text(src.ast.doc_comment_text(), src.ast.short_label())
-    }
+    Some(res)
 }
 
 pub(crate) fn type_of(db: &RootDatabase, frange: FileRange) -> Option<String> {
@@ -675,21 +714,4 @@ fn func(foo: i32) { if true { <|>foo; }; }
         assert_eq!(trim_markup_opt(hover.info.first()), Some("enum Thing"));
         assert_eq!(hover.info.is_exact(), true);
     }
-
-    #[test]
-    fn test_hover_shadowing_pat() {
-        let (analysis, position) = single_file_with_position(
-            "
-            fn x() {}
-
-            fn y() {
-                let x = 0i32;
-                x<|>;
-            }
-            ",
-        );
-        let hover = analysis.hover(position).unwrap().unwrap();
-        assert_eq!(trim_markup_opt(hover.info.first()), Some("i32"));
-        assert_eq!(hover.info.is_exact(), true);
-    }
 }
diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs
index 8741e736f5..dbebf50a62 100644
--- a/crates/ra_ide_api/src/lib.rs
+++ b/crates/ra_ide_api/src/lib.rs
@@ -242,21 +242,12 @@ pub struct CallInfo {
 }
 
 /// `AnalysisHost` stores the current state of the world.
-#[derive(Debug)]
+#[derive(Debug, Default)]
 pub struct AnalysisHost {
     db: db::RootDatabase,
 }
 
-impl Default for AnalysisHost {
-    fn default() -> AnalysisHost {
-        AnalysisHost::new(None)
-    }
-}
-
 impl AnalysisHost {
-    pub fn new(lru_capcity: Option<usize>) -> AnalysisHost {
-        AnalysisHost { db: db::RootDatabase::new(lru_capcity) }
-    }
     /// Returns a snapshot of the current state, which you can query for
     /// semantic information.
     pub fn analysis(&self) -> Analysis {
diff --git a/crates/ra_ide_api/src/references.rs b/crates/ra_ide_api/src/references.rs
index 12cdc6a6d1..a75042b76a 100644
--- a/crates/ra_ide_api/src/references.rs
+++ b/crates/ra_ide_api/src/references.rs
@@ -148,9 +148,9 @@ fn rename_mod(
     let mut file_system_edits = Vec::new();
     if let Some(module) = source_binder::module_from_declaration(db, position.file_id, &ast_module)
     {
-        let src = module.definition_source(db);
-        let file_id = src.file_id.as_original_file();
-        match src.ast {
+        let (file_id, module_source) = module.definition_source(db);
+        let file_id = file_id.as_original_file();
+        match module_source {
             ModuleSource::SourceFile(..) => {
                 let mod_path: RelativePathBuf = db.file_relative_path(file_id);
                 // mod is defined in path/to/dir/mod.rs
diff --git a/crates/ra_lsp_server/src/init.rs b/crates/ra_lsp_server/src/init.rs
index b894b449d7..1b77e03125 100644
--- a/crates/ra_lsp_server/src/init.rs
+++ b/crates/ra_lsp_server/src/init.rs
@@ -17,17 +17,11 @@ pub struct InitializationOptions {
     /// Defaults to `true`
     #[serde(deserialize_with = "nullable_bool_true")]
     pub show_workspace_loaded: bool,
-
-    pub lru_capacity: Option<usize>,
 }
 
 impl Default for InitializationOptions {
     fn default() -> InitializationOptions {
-        InitializationOptions {
-            publish_decorations: false,
-            show_workspace_loaded: true,
-            lru_capacity: None,
-        }
+        InitializationOptions { publish_decorations: false, show_workspace_loaded: true }
     }
 }
 
@@ -60,10 +54,8 @@ mod test {
         assert_eq!(default, serde_json::from_str(r#"{}"#).unwrap());
         assert_eq!(
             default,
-            serde_json::from_str(
-                r#"{"publishDecorations":null, "showWorkspaceLoaded":null, "lruCapacity":null}"#
-            )
-            .unwrap()
+            serde_json::from_str(r#"{"publishDecorations":null, "showWorkspaceLoaded":null}"#)
+                .unwrap()
         );
     }
 }
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs
index 0790ea472e..090fb9b1b0 100644
--- a/crates/ra_lsp_server/src/main_loop.rs
+++ b/crates/ra_lsp_server/src/main_loop.rs
@@ -73,7 +73,7 @@ pub fn main_loop(
         loaded_workspaces
     };
 
-    let mut state = WorldState::new(ws_roots, workspaces, options.lru_capacity);
+    let mut state = WorldState::new(ws_roots, workspaces);
 
     let pool = ThreadPool::new(THREADPOOL_SIZE);
     let (task_sender, task_receiver) = unbounded::<Task>();
diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs
index f9ce570ca3..cd8df4fdba 100644
--- a/crates/ra_lsp_server/src/world.rs
+++ b/crates/ra_lsp_server/src/world.rs
@@ -46,11 +46,7 @@ pub struct WorldSnapshot {
 }
 
 impl WorldState {
-    pub fn new(
-        folder_roots: Vec<PathBuf>,
-        workspaces: Vec<ProjectWorkspace>,
-        lru_capacity: Option<usize>,
-    ) -> WorldState {
+    pub fn new(folder_roots: Vec<PathBuf>, workspaces: Vec<ProjectWorkspace>) -> WorldState {
         let mut change = AnalysisChange::new();
 
         let mut roots = Vec::new();
@@ -78,7 +74,7 @@ impl WorldState {
         }
         change.set_crate_graph(crate_graph);
 
-        let mut analysis_host = AnalysisHost::new(lru_capacity);
+        let mut analysis_host = AnalysisHost::default();
         analysis_host.apply_change(change);
         WorldState {
             roots_to_scan,
diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs
index 7718fbe6a1..e85147e9e2 100644
--- a/crates/ra_parser/src/grammar/items.rs
+++ b/crates/ra_parser/src/grammar/items.rs
@@ -107,6 +107,10 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Resul
         p.bump_remap(T![default]);
         has_mods = true;
     }
+    if p.at(IDENT) && p.at_contextual_kw("existential") && p.nth(1) == T![type] {
+        p.bump_remap(T![existential]);
+        has_mods = true;
+    }
 
     // items
     match p.current() {
@@ -165,12 +169,17 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Resul
             traits::impl_block(p);
             m.complete(p, IMPL_BLOCK);
         }
+        // test existential_type
+        // existential type Foo: Fn() -> usize;
+        T![type] => {
+            type_def(p, m);
+        }
         _ => {
             if !has_visibility && !has_mods {
                 return Err(m);
             } else {
                 if has_mods {
-                    p.error("expected fn, trait or impl");
+                    p.error("expected existential, fn, trait or impl");
                 } else {
                     p.error("expected an item");
                 }
@@ -187,7 +196,9 @@ fn items_without_modifiers(p: &mut Parser, m: Marker) -> Result<(), Marker> {
         // test extern_crate
         // extern crate foo;
         T![extern] if la == T![crate] => extern_crate_item(p, m),
-        T![type] => type_def(p, m),
+        T![type] => {
+            type_def(p, m);
+        }
         T![mod] => mod_item(p, m),
         T![struct] => {
             // test struct_items
@@ -308,7 +319,6 @@ fn type_def(p: &mut Parser, m: Marker) {
     // test type_item_where_clause
     // type Foo where Foo: Copy = ();
     type_params::opt_where_clause(p);
-
     if p.eat(T![=]) {
         types::type_(p);
     }
diff --git a/crates/ra_parser/src/syntax_kind/generated.rs b/crates/ra_parser/src/syntax_kind/generated.rs
index 2c021f3e9d..036415eacd 100644
--- a/crates/ra_parser/src/syntax_kind/generated.rs
+++ b/crates/ra_parser/src/syntax_kind/generated.rs
@@ -106,6 +106,7 @@ pub enum SyntaxKind {
     TRY_KW,
     AUTO_KW,
     DEFAULT_KW,
+    EXISTENTIAL_KW,
     UNION_KW,
     INT_NUMBER,
     FLOAT_NUMBER,
@@ -336,6 +337,7 @@ macro_rules! T {
     (try) => { $crate::SyntaxKind::TRY_KW };
     (auto) => { $crate::SyntaxKind::AUTO_KW };
     (default) => { $crate::SyntaxKind::DEFAULT_KW };
+    (existential) => { $crate::SyntaxKind::EXISTENTIAL_KW };
     (union) => { $crate::SyntaxKind::UNION_KW };
 }
 
@@ -394,6 +396,7 @@ impl SyntaxKind {
             | TRY_KW
             | AUTO_KW
             | DEFAULT_KW
+            | EXISTENTIAL_KW
             | UNION_KW
                 => true,
             _ => false
@@ -566,6 +569,7 @@ impl SyntaxKind {
             TRY_KW => &SyntaxInfo { name: "TRY_KW" },
             AUTO_KW => &SyntaxInfo { name: "AUTO_KW" },
             DEFAULT_KW => &SyntaxInfo { name: "DEFAULT_KW" },
+            EXISTENTIAL_KW => &SyntaxInfo { name: "EXISTENTIAL_KW" },
             UNION_KW => &SyntaxInfo { name: "UNION_KW" },
             INT_NUMBER => &SyntaxInfo { name: "INT_NUMBER" },
             FLOAT_NUMBER => &SyntaxInfo { name: "FLOAT_NUMBER" },
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
index 1c2714307a..eab55058b9 100644
--- a/crates/ra_syntax/src/grammar.ron
+++ b/crates/ra_syntax/src/grammar.ron
@@ -100,6 +100,7 @@ Grammar(
     contextual_keywords: [
         "auto",
         "default",
+        "existential",
         "union",
     ],
     literals: [
diff --git a/docs/dev/architecture.md b/docs/dev/architecture.md
index cf714d659e..890b18fcd7 100644
--- a/docs/dev/architecture.md
+++ b/docs/dev/architecture.md
@@ -50,15 +50,15 @@ processes. These are outlined below:
   the grammar described in [grammar.ron]:
   - [ast/generated.rs][ast generated] in `ra_syntax` based on
     [ast/generated.tera.rs][ast source]
-  - [syntax_kind/generated.rs][syntax_kind generated] in `ra_syntax` based on
-    [syntax_kind/generated.tera.rs][syntax_kind source]
+  - [syntax_kinds/generated.rs][syntax_kinds generated] in `ra_syntax` based on
+    [syntax_kinds/generated.tera.rs][syntax_kinds source]
 
 [tera]: https://tera.netlify.com/
-[grammar.ron]: ../../crates/ra_syntax/src/grammar.ron
-[ast generated]: ../../crates/ra_syntax/src/ast/generated.rs
-[ast source]: ../../crates/ra_syntax/src/ast/generated.rs.tera
-[syntax_kind generated]: ../../crates/ra_parser/src/syntax_kind/generated.rs
-[syntax_kind source]: ../../crates/ra_parser/src/syntax_kind/generated.rs.tera
+[grammar.ron]: ./crates/ra_syntax/src/grammar.ron
+[ast generated]: ./crates/ra_syntax/src/ast/generated.rs
+[ast source]: ./crates/ra_syntax/src/ast/generated.rs.tera
+[syntax_kinds generated]: ./crates/ra_syntax/src/syntax_kinds/generated.rs
+[syntax_kinds source]: ./crates/ra_syntax/src/syntax_kinds/generated.rs.tera
 
 
 ## Code Walk-Through
diff --git a/editors/code/package.json b/editors/code/package.json
index c2ed8d1268..05c8083949 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -232,11 +232,6 @@
                     ],
                     "default": "off",
                     "description": "Trace output of cargo-watch"
-                },
-                "rust-analyzer.lruCapacity": {
-                    "type": "number",
-                    "default": null,
-                    "description": "Number of syntax trees rust-analyzer keeps in memory"
                 }
             }
         },
diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts
index 3024546d25..8d73a6b340 100644
--- a/editors/code/src/config.ts
+++ b/editors/code/src/config.ts
@@ -19,7 +19,6 @@ export class Config {
     public enableEnhancedTyping = true;
     public raLspServerPath = RA_LSP_DEBUG || 'ra_lsp_server';
     public showWorkspaceLoadedNotification = true;
-    public lruCapacity: null | number = null;
     public cargoWatchOptions: CargoWatchOptions = {
         enableOnStartup: 'ask',
         trace: 'off',
@@ -110,8 +109,5 @@ export class Config {
                 ''
             );
         }
-        if (config.has('lruCapacity')) {
-            this.lruCapacity = config.get('lruCapacity') as number;
-        }
     }
 }
diff --git a/editors/code/src/server.ts b/editors/code/src/server.ts
index 7029142fdc..81c2b3fff2 100644
--- a/editors/code/src/server.ts
+++ b/editors/code/src/server.ts
@@ -35,8 +35,7 @@ export class Server {
             initializationOptions: {
                 publishDecorations: true,
                 showWorkspaceLoaded:
-                    Server.config.showWorkspaceLoadedNotification,
-                lruCapacity: Server.config.lruCapacity
+                    Server.config.showWorkspaceLoadedNotification
             },
             traceOutputChannel
         };


Test patch:
diff --git a/crates/ra_syntax/tests/data/parser/err/0011_extern_struct.txt b/crates/ra_syntax/tests/data/parser/err/0011_extern_struct.txt
index 033dac2aa9..381147dc0a 100644
--- a/crates/ra_syntax/tests/data/parser/err/0011_extern_struct.txt
+++ b/crates/ra_syntax/tests/data/parser/err/0011_extern_struct.txt
@@ -10,4 +10,4 @@ SOURCE_FILE@[0; 19)
       IDENT@[14; 17) "Foo"
     SEMI@[17; 18) ";"
   WHITESPACE@[18; 19) "\n"
-error 6: expected fn, trait or impl
+error 6: expected existential, fn, trait or impl
diff --git a/crates/ra_syntax/tests/data/parser/inline/err/0010_wrong_order_fns.txt b/crates/ra_syntax/tests/data/parser/inline/err/0010_wrong_order_fns.txt
index 9eb4c9b36b..b1ef210d3f 100644
--- a/crates/ra_syntax/tests/data/parser/inline/err/0010_wrong_order_fns.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/err/0010_wrong_order_fns.txt
@@ -35,5 +35,5 @@ SOURCE_FILE@[0; 50)
       L_CURLY@[47; 48) "{"
       R_CURLY@[48; 49) "}"
   WHITESPACE@[49; 50) "\n"
-error 5: expected fn, trait or impl
-error 31: expected fn, trait or impl
+error 5: expected existential, fn, trait or impl
+error 31: expected existential, fn, trait or impl
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0131_existential_type.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0131_existential_type.rs
new file mode 100644
index 0000000000..23baf7145c
--- /dev/null
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0131_existential_type.rs
@@ -0,0 +1,1 @@
+existential type Foo: Fn() -> usize;
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0131_existential_type.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0131_existential_type.txt
new file mode 100644
index 0000000000..6bfac985a9
--- /dev/null
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0131_existential_type.txt
@@ -0,0 +1,31 @@
+SOURCE_FILE@[0; 37)
+  TYPE_ALIAS_DEF@[0; 36)
+    EXISTENTIAL_KW@[0; 11) "existential"
+    WHITESPACE@[11; 12) " "
+    TYPE_KW@[12; 16) "type"
+    WHITESPACE@[16; 17) " "
+    NAME@[17; 20)
+      IDENT@[17; 20) "Foo"
+    COLON@[20; 21) ":"
+    WHITESPACE@[21; 22) " "
+    TYPE_BOUND_LIST@[22; 35)
+      TYPE_BOUND@[22; 35)
+        PATH_TYPE@[22; 35)
+          PATH@[22; 35)
+            PATH_SEGMENT@[22; 35)
+              NAME_REF@[22; 24)
+                IDENT@[22; 24) "Fn"
+              PARAM_LIST@[24; 26)
+                L_PAREN@[24; 25) "("
+                R_PAREN@[25; 26) ")"
+              WHITESPACE@[26; 27) " "
+              RET_TYPE@[27; 35)
+                THIN_ARROW@[27; 29) "->"
+                WHITESPACE@[29; 30) " "
+                PATH_TYPE@[30; 35)
+                  PATH@[30; 35)
+                    PATH_SEGMENT@[30; 35)
+                      NAME_REF@[30; 35)
+                        IDENT@[30; 35) "usize"
+    SEMI@[35; 36) ";"
+  WHITESPACE@[36; 37) "\n"