Repository: rust-analyzer/rust-analyzer
Pull request #2357 (2019-11-22 15:05:45)

Expand file! to dummy ""
See https://github.com/rust-analyzer/rust-analyzer/pull/2355#issuecomment-557541873


Patch:
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 3daf7488ed..72c9b466f7 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -10,10 +10,10 @@ use hir_def::{
     adt::VariantData,
     body::scope::ExprScopes,
     builtin_type::BuiltinType,
-    data::TraitData,
     nameres::per_ns::PerNs,
     resolver::{HasResolver, TypeNs},
-    type_ref::TypeRef,
+    traits::TraitData,
+    type_ref::{Mutability, TypeRef},
     ContainerId, CrateModuleId, HasModule, ImplId, LocalEnumVariantId, LocalStructFieldId, Lookup,
     ModuleId, UnionId,
 };
@@ -561,6 +561,77 @@ pub struct Function {
     pub(crate) id: FunctionId,
 }
 
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct FnData {
+    pub(crate) name: Name,
+    pub(crate) params: Vec<TypeRef>,
+    pub(crate) ret_type: TypeRef,
+    /// True if the first param is `self`. This is relevant to decide whether this
+    /// can be called as a method.
+    pub(crate) has_self_param: bool,
+}
+
+impl FnData {
+    pub(crate) fn fn_data_query(
+        db: &(impl DefDatabase + AstDatabase),
+        func: Function,
+    ) -> Arc<FnData> {
+        let src = func.source(db);
+        let name = src.value.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.value.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)
+                } else {
+                    let self_type = TypeRef::Path(name::SELF_TYPE.into());
+                    match self_param.kind() {
+                        ast::SelfParamKind::Owned => self_type,
+                        ast::SelfParamKind::Ref => {
+                            TypeRef::Reference(Box::new(self_type), Mutability::Shared)
+                        }
+                        ast::SelfParamKind::MutRef => {
+                            TypeRef::Reference(Box::new(self_type), Mutability::Mut)
+                        }
+                    }
+                };
+                params.push(self_type);
+                has_self_param = true;
+            }
+            for param in param_list.params() {
+                let type_ref = TypeRef::from_ast_opt(param.ascribed_type());
+                params.push(type_ref);
+            }
+        }
+        let ret_type = if let Some(type_ref) = src.value.ret_type().and_then(|rt| rt.type_ref()) {
+            TypeRef::from_ast(type_ref)
+        } else {
+            TypeRef::unit()
+        };
+
+        let sig = FnData { name, params, ret_type, has_self_param };
+        Arc::new(sig)
+    }
+    pub fn name(&self) -> &Name {
+        &self.name
+    }
+
+    pub fn params(&self) -> &[TypeRef] {
+        &self.params
+    }
+
+    pub fn ret_type(&self) -> &TypeRef {
+        &self.ret_type
+    }
+
+    /// True if the first arg is `self`. This is relevant to decide whether this
+    /// can be called as a method.
+    pub fn has_self_param(&self) -> bool {
+        self.has_self_param
+    }
+}
+
 impl Function {
     pub fn module(self, db: &impl DefDatabase) -> Module {
         self.id.lookup(db).module(db).into()
@@ -571,15 +642,7 @@ impl Function {
     }
 
     pub fn name(self, db: &impl HirDatabase) -> Name {
-        db.function_data(self.id).name.clone()
-    }
-
-    pub fn has_self_param(self, db: &impl HirDatabase) -> bool {
-        db.function_data(self.id).has_self_param
-    }
-
-    pub fn params(self, db: &impl HirDatabase) -> Vec<TypeRef> {
-        db.function_data(self.id).params.clone()
+        self.data(db).name.clone()
     }
 
     pub(crate) fn body_source_map(self, db: &impl HirDatabase) -> Arc<BodySourceMap> {
@@ -594,6 +657,10 @@ impl Function {
         db.type_for_def(self.into(), Namespace::Values)
     }
 
+    pub fn data(self, db: &impl HirDatabase) -> Arc<FnData> {
+        db.fn_data(self)
+    }
+
     pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> {
         db.infer(self.into())
     }
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index 8b9af05652..1cfcb2fd2f 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -16,15 +16,15 @@ use crate::{
         CallableDef, FnSig, GenericPredicate, InferenceResult, Namespace, Substs, Ty, TypableDef,
         TypeCtor,
     },
-    Const, ConstData, Crate, DefWithBody, GenericDef, ImplBlock, Module, Static, StructField,
-    Trait,
+    Const, ConstData, Crate, DefWithBody, FnData, Function, GenericDef, ImplBlock, Module, Static,
+    StructField, Trait,
 };
 
 pub use hir_def::db::{
     BodyQuery, BodyWithSourceMapQuery, CrateDefMapQuery, DefDatabase2, DefDatabase2Storage,
-    EnumDataQuery, ExprScopesQuery, FunctionDataQuery, GenericParamsQuery, ImplDataQuery,
-    InternDatabase, InternDatabaseStorage, RawItemsQuery, RawItemsWithSourceMapQuery,
-    StructDataQuery, TraitDataQuery, TypeAliasDataQuery,
+    EnumDataQuery, ExprScopesQuery, GenericParamsQuery, ImplDataQuery, InternDatabase,
+    InternDatabaseStorage, RawItemsQuery, RawItemsWithSourceMapQuery, StructDataQuery,
+    TraitDataQuery, TypeAliasDataQuery,
 };
 pub use hir_expand::db::{
     AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery,
@@ -35,6 +35,9 @@ pub use hir_expand::db::{
 #[salsa::query_group(DefDatabaseStorage)]
 #[salsa::requires(AstDatabase)]
 pub trait DefDatabase: HirDebugDatabase + DefDatabase2 {
+    #[salsa::invoke(FnData::fn_data_query)]
+    fn fn_data(&self, func: Function) -> Arc<FnData>;
+
     #[salsa::invoke(ConstData::const_data_query)]
     fn const_data(&self, konst: Const) -> Arc<ConstData>;
 
diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs
index 334eeebacd..774fa1d964 100644
--- a/crates/ra_hir/src/impl_block.rs
+++ b/crates/ra_hir/src/impl_block.rs
@@ -18,11 +18,11 @@ impl HasSource for ImplBlock {
 
 impl ImplBlock {
     pub fn target_trait(&self, db: &impl DefDatabase) -> Option<TypeRef> {
-        db.impl_data(self.id).target_trait.clone()
+        db.impl_data(self.id).target_trait().cloned()
     }
 
     pub fn target_type(&self, db: &impl DefDatabase) -> TypeRef {
-        db.impl_data(self.id).target_type.clone()
+        db.impl_data(self.id).target_type().clone()
     }
 
     pub fn target_ty(&self, db: &impl HirDatabase) -> Ty {
@@ -35,11 +35,11 @@ impl ImplBlock {
     }
 
     pub fn items(&self, db: &impl DefDatabase) -> Vec<AssocItem> {
-        db.impl_data(self.id).items.iter().map(|it| (*it).into()).collect()
+        db.impl_data(self.id).items().iter().map(|it| (*it).into()).collect()
     }
 
     pub fn is_negative(&self, db: &impl DefDatabase) -> bool {
-        db.impl_data(self.id).is_negative
+        db.impl_data(self.id).is_negative()
     }
 
     pub fn module(&self, db: &impl DefDatabase) -> Module {
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index d29cc92580..8535629ca7 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -55,9 +55,9 @@ pub use crate::{
         docs::{DocDef, Docs, Documentation},
         src::{HasBodySource, HasSource},
         Adt, AssocItem, Const, ConstData, Container, Crate, CrateDependency, DefWithBody, Enum,
-        EnumVariant, FieldSource, Function, GenericDef, GenericParam, HasBody, ImplBlock, Local,
-        MacroDef, Module, ModuleDef, ModuleSource, ScopeDef, Static, Struct, StructField, Trait,
-        TypeAlias, Union, VariantDef,
+        EnumVariant, FieldSource, FnData, Function, GenericDef, GenericParam, HasBody, ImplBlock,
+        Local, MacroDef, Module, ModuleDef, ModuleSource, ScopeDef, Static, Struct, StructField,
+        Trait, TypeAlias, Union, VariantDef,
     },
     expr::ExprScopes,
     from_source::FromSource,
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index 6e07ab86e8..69b13baefb 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -22,7 +22,6 @@ use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
 use rustc_hash::FxHashMap;
 
 use hir_def::{
-    data::FunctionData,
     path::known,
     resolver::{HasResolver, Resolver, TypeNs},
     type_ref::{Mutability, TypeRef},
@@ -44,8 +43,8 @@ use crate::{
     db::HirDatabase,
     expr::{BindingAnnotation, Body, ExprId, PatId},
     ty::infer::diagnostics::InferenceDiagnostic,
-    Adt, AssocItem, ConstData, DefWithBody, FloatTy, Function, HasBody, IntTy, Path, StructField,
-    Trait, VariantDef,
+    Adt, AssocItem, ConstData, DefWithBody, FloatTy, FnData, Function, HasBody, IntTy, Path,
+    StructField, Trait, VariantDef,
 };
 
 macro_rules! ty_app {
@@ -71,7 +70,7 @@ pub fn infer_query(db: &impl HirDatabase, def: DefWithBody) -> Arc<InferenceResu
 
     match def {
         DefWithBody::Const(ref c) => ctx.collect_const(&c.data(db)),
-        DefWithBody::Function(ref f) => ctx.collect_fn(&db.function_data(f.id)),
+        DefWithBody::Function(ref f) => ctx.collect_fn(&f.data(db)),
         DefWithBody::Static(ref s) => ctx.collect_const(&s.data(db)),
     }
 
@@ -563,14 +562,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
         self.return_ty = self.make_ty(data.type_ref());
     }
 
-    fn collect_fn(&mut self, data: &FunctionData) {
+    fn collect_fn(&mut self, data: &FnData) {
         let body = Arc::clone(&self.body); // avoid borrow checker problem
-        for (type_ref, pat) in data.params.iter().zip(body.params()) {
+        for (type_ref, pat) in data.params().iter().zip(body.params()) {
             let ty = self.make_ty(type_ref);
 
             self.infer_pat(*pat, &ty, BindingMode::default());
         }
-        self.return_ty = self.make_ty(&data.ret_type);
+        self.return_ty = self.make_ty(data.ret_type());
     }
 
     fn infer_body(&mut self) {
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index 42daa9cb93..75c5525692 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -622,10 +622,10 @@ pub(crate) fn generic_defaults_query(db: &impl HirDatabase, def: GenericDef) ->
 }
 
 fn fn_sig_for_fn(db: &impl HirDatabase, def: Function) -> FnSig {
-    let data = db.function_data(def.id);
+    let data = def.data(db);
     let resolver = def.id.resolver(db);
-    let params = data.params.iter().map(|tr| Ty::from_hir(db, &resolver, tr)).collect::<Vec<_>>();
-    let ret = Ty::from_hir(db, &resolver, &data.ret_type);
+    let params = data.params().iter().map(|tr| Ty::from_hir(db, &resolver, tr)).collect::<Vec<_>>();
+    let ret = Ty::from_hir(db, &resolver, data.ret_type());
     FnSig::from_params_and_return(params, ret)
 }
 
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index f84aae26ee..64adb814d3 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -291,9 +291,9 @@ fn is_valid_candidate(
 ) -> bool {
     match item {
         AssocItem::Function(m) => {
-            let data = db.function_data(m.id);
-            name.map_or(true, |name| data.name == *name)
-                && (data.has_self_param || mode == LookupMode::Path)
+            let data = m.data(db);
+            name.map_or(true, |name| data.name() == name)
+                && (data.has_self_param() || mode == LookupMode::Path)
         }
         AssocItem::Const(c) => {
             name.map_or(true, |name| Some(name) == c.name(db).as_ref())
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs
deleted file mode 100644
index ba47629db3..0000000000
--- a/crates/ra_hir_def/src/data.rs
+++ /dev/null
@@ -1,192 +0,0 @@
-//! Contains basic data about various HIR declarations.
-
-use std::sync::Arc;
-
-use hir_expand::{
-    name::{self, AsName, Name},
-    AstId,
-};
-use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner};
-
-use crate::{
-    db::DefDatabase2,
-    type_ref::{Mutability, TypeRef},
-    AssocItemId, AstItemDef, ConstLoc, ContainerId, FunctionId, FunctionLoc, HasSource, ImplId,
-    Intern, Lookup, TraitId, TypeAliasId, TypeAliasLoc,
-};
-
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub struct FunctionData {
-    pub name: Name,
-    pub params: Vec<TypeRef>,
-    pub ret_type: TypeRef,
-    /// True if the first param is `self`. This is relevant to decide whether this
-    /// can be called as a method.
-    pub has_self_param: bool,
-}
-
-impl FunctionData {
-    pub(crate) fn fn_data_query(db: &impl DefDatabase2, func: FunctionId) -> Arc<FunctionData> {
-        let src = func.lookup(db).source(db);
-        let name = src.value.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.value.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)
-                } else {
-                    let self_type = TypeRef::Path(name::SELF_TYPE.into());
-                    match self_param.kind() {
-                        ast::SelfParamKind::Owned => self_type,
-                        ast::SelfParamKind::Ref => {
-                            TypeRef::Reference(Box::new(self_type), Mutability::Shared)
-                        }
-                        ast::SelfParamKind::MutRef => {
-                            TypeRef::Reference(Box::new(self_type), Mutability::Mut)
-                        }
-                    }
-                };
-                params.push(self_type);
-                has_self_param = true;
-            }
-            for param in param_list.params() {
-                let type_ref = TypeRef::from_ast_opt(param.ascribed_type());
-                params.push(type_ref);
-            }
-        }
-        let ret_type = if let Some(type_ref) = src.value.ret_type().and_then(|rt| rt.type_ref()) {
-            TypeRef::from_ast(type_ref)
-        } else {
-            TypeRef::unit()
-        };
-
-        let sig = FunctionData { name, params, ret_type, has_self_param };
-        Arc::new(sig)
-    }
-}
-
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub struct TypeAliasData {
-    pub name: Name,
-    pub type_ref: Option<TypeRef>,
-}
-
-impl TypeAliasData {
-    pub(crate) fn type_alias_data_query(
-        db: &impl DefDatabase2,
-        typ: TypeAliasId,
-    ) -> Arc<TypeAliasData> {
-        let node = typ.lookup(db).source(db).value;
-        let name = node.name().map_or_else(Name::missing, |n| n.as_name());
-        let type_ref = node.type_ref().map(TypeRef::from_ast);
-        Arc::new(TypeAliasData { name, type_ref })
-    }
-}
-
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub struct TraitData {
-    pub name: Option<Name>,
-    pub items: Vec<AssocItemId>,
-    pub auto: bool,
-}
-
-impl TraitData {
-    pub(crate) fn trait_data_query(db: &impl DefDatabase2, tr: TraitId) -> Arc<TraitData> {
-        let src = tr.source(db);
-        let name = src.value.name().map(|n| n.as_name());
-        let auto = src.value.is_auto();
-        let ast_id_map = db.ast_id_map(src.file_id);
-        let items = if let Some(item_list) = src.value.item_list() {
-            item_list
-                .impl_items()
-                .map(|item_node| match item_node {
-                    ast::ImplItem::FnDef(it) => FunctionLoc {
-                        container: ContainerId::TraitId(tr),
-                        ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
-                    }
-                    .intern(db)
-                    .into(),
-                    ast::ImplItem::ConstDef(it) => ConstLoc {
-                        container: ContainerId::TraitId(tr),
-                        ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
-                    }
-                    .intern(db)
-                    .into(),
-                    ast::ImplItem::TypeAliasDef(it) => TypeAliasLoc {
-                        container: ContainerId::TraitId(tr),
-                        ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
-                    }
-                    .intern(db)
-                    .into(),
-                })
-                .collect()
-        } else {
-            Vec::new()
-        };
-        Arc::new(TraitData { name, items, auto })
-    }
-
-    pub fn associated_types(&self) -> impl Iterator<Item = TypeAliasId> + '_ {
-        self.items.iter().filter_map(|item| match item {
-            AssocItemId::TypeAliasId(t) => Some(*t),
-            _ => None,
-        })
-    }
-}
-
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub struct ImplData {
-    pub target_trait: Option<TypeRef>,
-    pub target_type: TypeRef,
-    pub items: Vec<AssocItemId>,
-    pub is_negative: bool,
-}
-
-impl ImplData {
-    pub(crate) fn impl_data_query(db: &impl DefDatabase2, id: ImplId) -> Arc<ImplData> {
-        let src = id.source(db);
-        let items = db.ast_id_map(src.file_id);
-
-        let target_trait = src.value.target_trait().map(TypeRef::from_ast);
-        let target_type = TypeRef::from_ast_opt(src.value.target_type());
-        let is_negative = src.value.is_negative();
-
-        let items = if let Some(item_list) = src.value.item_list() {
-            item_list
-                .impl_items()
-                .map(|item_node| match item_node {
-                    ast::ImplItem::FnDef(it) => {
-                        let def = FunctionLoc {
-                            container: ContainerId::ImplId(id),
-                            ast_id: AstId::new(src.file_id, items.ast_id(&it)),
-                        }
-                        .intern(db);
-                        def.into()
-                    }
-                    ast::ImplItem::ConstDef(it) => {
-                        let def = ConstLoc {
-                            container: ContainerId::ImplId(id),
-                            ast_id: AstId::new(src.file_id, items.ast_id(&it)),
-                        }
-                        .intern(db);
-                        def.into()
-                    }
-                    ast::ImplItem::TypeAliasDef(it) => {
-                        let def = TypeAliasLoc {
-                            container: ContainerId::ImplId(id),
-                            ast_id: AstId::new(src.file_id, items.ast_id(&it)),
-                        }
-                        .intern(db);
-                        def.into()
-                    }
-                })
-                .collect()
-        } else {
-            Vec::new()
-        };
-
-        let res = ImplData { target_trait, target_type, items, is_negative };
-        Arc::new(res)
-    }
-}
diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs
index 8c1784ec9d..5bbdaa4b20 100644
--- a/crates/ra_hir_def/src/db.rs
+++ b/crates/ra_hir_def/src/db.rs
@@ -8,14 +8,15 @@ use ra_syntax::ast;
 use crate::{
     adt::{EnumData, StructData},
     body::{scope::ExprScopes, Body, BodySourceMap},
-    data::{FunctionData, ImplData, TraitData, TypeAliasData},
     generics::GenericParams,
+    impls::ImplData,
     nameres::{
         raw::{ImportSourceMap, RawItems},
         CrateDefMap,
     },
-    DefWithBodyId, EnumId, FunctionId, GenericDefId, ImplId, ItemLoc, StructOrUnionId, TraitId,
-    TypeAliasId,
+    traits::TraitData,
+    type_alias::TypeAliasData,
+    DefWithBodyId, EnumId, GenericDefId, ImplId, ItemLoc, StructOrUnionId, TraitId, TypeAliasId,
 };
 
 #[salsa::query_group(InternDatabaseStorage)]
@@ -67,9 +68,6 @@ pub trait DefDatabase2: InternDatabase + AstDatabase {
     #[salsa::invoke(TypeAliasData::type_alias_data_query)]
     fn type_alias_data(&self, e: TypeAliasId) -> Arc<TypeAliasData>;
 
-    #[salsa::invoke(FunctionData::fn_data_query)]
-    fn function_data(&self, func: FunctionId) -> Arc<FunctionData>;
-
     #[salsa::invoke(Body::body_with_source_map_query)]
     fn body_with_source_map(&self, def: DefWithBodyId) -> (Arc<Body>, Arc<BodySourceMap>);
 
diff --git a/crates/ra_hir_def/src/impls.rs b/crates/ra_hir_def/src/impls.rs
new file mode 100644
index 0000000000..750a869f25
--- /dev/null
+++ b/crates/ra_hir_def/src/impls.rs
@@ -0,0 +1,86 @@
+//! Defines hir-level representation of impls.
+//!
+//! The handling is similar, but is not quite the same as for other items,
+//! because `impl`s don't have names.
+
+use std::sync::Arc;
+
+use hir_expand::AstId;
+use ra_syntax::ast;
+
+use crate::{
+    db::DefDatabase2, type_ref::TypeRef, AssocItemId, AstItemDef, ConstLoc, ContainerId,
+    FunctionLoc, ImplId, Intern, TypeAliasLoc,
+};
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct ImplData {
+    target_trait: Option<TypeRef>,
+    target_type: TypeRef,
+    items: Vec<AssocItemId>,
+    negative: bool,
+}
+
+impl ImplData {
+    pub(crate) fn impl_data_query(db: &impl DefDatabase2, id: ImplId) -> Arc<ImplData> {
+        let src = id.source(db);
+        let items = db.ast_id_map(src.file_id);
+
+        let target_trait = src.value.target_trait().map(TypeRef::from_ast);
+        let target_type = TypeRef::from_ast_opt(src.value.target_type());
+        let negative = src.value.is_negative();
+
+        let items = if let Some(item_list) = src.value.item_list() {
+            item_list
+                .impl_items()
+                .map(|item_node| match item_node {
+                    ast::ImplItem::FnDef(it) => {
+                        let def = FunctionLoc {
+                            container: ContainerId::ImplId(id),
+                            ast_id: AstId::new(src.file_id, items.ast_id(&it)),
+                        }
+                        .intern(db);
+                        def.into()
+                    }
+                    ast::ImplItem::ConstDef(it) => {
+                        let def = ConstLoc {
+                            container: ContainerId::ImplId(id),
+                            ast_id: AstId::new(src.file_id, items.ast_id(&it)),
+                        }
+                        .intern(db);
+                        def.into()
+                    }
+                    ast::ImplItem::TypeAliasDef(it) => {
+                        let def = TypeAliasLoc {
+                            container: ContainerId::ImplId(id),
+                            ast_id: AstId::new(src.file_id, items.ast_id(&it)),
+                        }
+                        .intern(db);
+                        def.into()
+                    }
+                })
+                .collect()
+        } else {
+            Vec::new()
+        };
+
+        let res = ImplData { target_trait, target_type, items, negative };
+        Arc::new(res)
+    }
+
+    pub fn target_trait(&self) -> Option<&TypeRef> {
+        self.target_trait.as_ref()
+    }
+
+    pub fn target_type(&self) -> &TypeRef {
+        &self.target_type
+    }
+
+    pub fn items(&self) -> &[AssocItemId] {
+        &self.items
+    }
+
+    pub fn is_negative(&self) -> bool {
+        self.negative
+    }
+}
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs
index 3a0420da0c..2681444629 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -13,12 +13,14 @@ pub mod path;
 pub mod type_ref;
 pub mod builtin_type;
 pub mod adt;
+pub mod impls;
 pub mod diagnostics;
 pub mod expr;
 pub mod body;
 pub mod generics;
+pub mod traits;
 pub mod resolver;
-pub mod data;
+pub mod type_alias;
 
 #[cfg(test)]
 mod test_db;
diff --git a/crates/ra_hir_def/src/traits.rs b/crates/ra_hir_def/src/traits.rs
new file mode 100644
index 0000000000..6c2d5b2a9f
--- /dev/null
+++ b/crates/ra_hir_def/src/traits.rs
@@ -0,0 +1,66 @@
+//! HIR for trait definitions.
+
+use std::sync::Arc;
+
+use hir_expand::{
+    name::{AsName, Name},
+    AstId,
+};
+
+use ra_syntax::ast::{self, NameOwner};
+
+use crate::{
+    db::DefDatabase2, AssocItemId, AstItemDef, ConstLoc, ContainerId, FunctionLoc, Intern, TraitId,
+    TypeAliasId, TypeAliasLoc,
+};
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct TraitData {
+    pub name: Option<Name>,
+    pub items: Vec<AssocItemId>,
+    pub auto: bool,
+}
+
+impl TraitData {
+    pub(crate) fn trait_data_query(db: &impl DefDatabase2, tr: TraitId) -> Arc<TraitData> {
+        let src = tr.source(db);
+        let name = src.value.name().map(|n| n.as_name());
+        let auto = src.value.is_auto();
+        let ast_id_map = db.ast_id_map(src.file_id);
+        let items = if let Some(item_list) = src.value.item_list() {
+            item_list
+                .impl_items()
+                .map(|item_node| match item_node {
+                    ast::ImplItem::FnDef(it) => FunctionLoc {
+                        container: ContainerId::TraitId(tr),
+                        ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
+                    }
+                    .intern(db)
+                    .into(),
+                    ast::ImplItem::ConstDef(it) => ConstLoc {
+                        container: ContainerId::TraitId(tr),
+                        ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
+                    }
+                    .intern(db)
+                    .into(),
+                    ast::ImplItem::TypeAliasDef(it) => TypeAliasLoc {
+                        container: ContainerId::TraitId(tr),
+                        ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
+                    }
+                    .intern(db)
+                    .into(),
+                })
+                .collect()
+        } else {
+            Vec::new()
+        };
+        Arc::new(TraitData { name, items, auto })
+    }
+
+    pub fn associated_types(&self) -> impl Iterator<Item = TypeAliasId> + '_ {
+        self.items.iter().filter_map(|item| match item {
+            AssocItemId::TypeAliasId(t) => Some(*t),
+            _ => None,
+        })
+    }
+}
diff --git a/crates/ra_hir_def/src/type_alias.rs b/crates/ra_hir_def/src/type_alias.rs
new file mode 100644
index 0000000000..c0b49aa7cc
--- /dev/null
+++ b/crates/ra_hir_def/src/type_alias.rs
@@ -0,0 +1,27 @@
+//! HIR for type aliases (i.e. the `type` keyword).
+
+use std::sync::Arc;
+
+use hir_expand::name::{AsName, Name};
+
+use ra_syntax::ast::NameOwner;
+
+use crate::{db::DefDatabase2, type_ref::TypeRef, HasSource, Lookup, TypeAliasId};
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct TypeAliasData {
+    pub name: Name,
+    pub type_ref: Option<TypeRef>,
+}
+
+impl TypeAliasData {
+    pub(crate) fn type_alias_data_query(
+        db: &impl DefDatabase2,
+        typ: TypeAliasId,
+    ) -> Arc<TypeAliasData> {
+        let node = typ.lookup(db).source(db).value;
+        let name = node.name().map_or_else(Name::missing, |n| n.as_name());
+        let type_ref = node.type_ref().map(TypeRef::from_ast);
+        Arc::new(TypeAliasData { name, type_ref })
+    }
+}
diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs
index 9628666d46..d7057e0054 100644
--- a/crates/ra_hir_expand/src/builtin_macro.rs
+++ b/crates/ra_hir_expand/src/builtin_macro.rs
@@ -10,6 +10,7 @@ use crate::quote;
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 pub enum BuiltinExpander {
+    File,
     Line,
     Stringify,
 }
@@ -22,6 +23,7 @@ impl BuiltinExpander {
         tt: &tt::Subtree,
     ) -> Result<tt::Subtree, mbe::ExpandError> {
         match self {
+            BuiltinExpander::File => file_expand(db, id, tt),
             BuiltinExpander::Line => line_expand(db, id, tt),
             BuiltinExpander::Stringify => stringify_expand(db, id, tt),
         }
@@ -34,7 +36,9 @@ pub fn find_builtin_macro(
     ast_id: AstId<ast::MacroCall>,
 ) -> Option<MacroDefId> {
     // FIXME: Better registering method
-    if ident == &name::LINE_MACRO {
+    if ident == &name::FILE_MACRO {
+        Some(MacroDefId { krate, ast_id, kind: MacroDefKind::BuiltIn(BuiltinExpander::File) })
+    } else if ident == &name::LINE_MACRO {
         Some(MacroDefId { krate, ast_id, kind: MacroDefKind::BuiltIn(BuiltinExpander::Line) })
     } else if ident == &name::STRINGIFY_MACRO {
         Some(MacroDefId { krate, ast_id, kind: MacroDefKind::BuiltIn(BuiltinExpander::Stringify) })
@@ -105,3 +109,23 @@ fn stringify_expand(
 
     Ok(expanded)
 }
+
+fn file_expand(
+    db: &dyn AstDatabase,
+    id: MacroCallId,
+    _tt: &tt::Subtree,
+) -> Result<tt::Subtree, mbe::ExpandError> {
+    let loc = db.lookup_intern_macro(id);
+    let macro_call = loc.ast_id.to_node(db);
+    let _ = macro_call.token_tree().ok_or_else(|| mbe::ExpandError::UnexpectedToken)?;
+
+    // FIXME: RA purposefully lacks knowledge of absolute file names
+    // so just return "".
+    let file_name = "";
+
+    let expanded = quote! {
+        #file_name
+    };
+
+    Ok(expanded)
+}
diff --git a/crates/ra_hir_expand/src/name.rs b/crates/ra_hir_expand/src/name.rs
index c3f7e77a5a..05fe6afd9b 100644
--- a/crates/ra_hir_expand/src/name.rs
+++ b/crates/ra_hir_expand/src/name.rs
@@ -142,5 +142,6 @@ pub const TARGET_TYPE: Name = Name::new_inline_ascii(6, b"Target");
 pub const BOX_TYPE: Name = Name::new_inline_ascii(3, b"Box");
 
 // Builtin Macros
+pub const FILE_MACRO: Name = Name::new_inline_ascii(4, b"file");
 pub const LINE_MACRO: Name = Name::new_inline_ascii(4, b"line");
 pub const STRINGIFY_MACRO: Name = Name::new_inline_ascii(9, b"stringify");
diff --git a/crates/ra_ide_api/src/call_info.rs b/crates/ra_ide_api/src/call_info.rs
index 7c367230e7..41ee815112 100644
--- a/crates/ra_ide_api/src/call_info.rs
+++ b/crates/ra_ide_api/src/call_info.rs
@@ -30,7 +30,7 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
             let (callable_def, _subst) = analyzer.type_of(db, &expr.expr()?)?.as_callable()?;
             match callable_def {
                 hir::CallableDef::Function(it) => {
-                    (CallInfo::with_fn(db, it), it.has_self_param(db))
+                    (CallInfo::with_fn(db, it), it.data(db).has_self_param())
                 }
                 hir::CallableDef::Struct(it) => (CallInfo::with_struct(db, it)?, false),
                 hir::CallableDef::EnumVariant(it) => (CallInfo::with_enum_variant(db, it)?, false),
@@ -38,7 +38,7 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
         }
         FnCallNode::MethodCallExpr(expr) => {
             let function = analyzer.resolve_method_call(&expr)?;
-            (CallInfo::with_fn(db, function), function.has_self_param(db))
+            (CallInfo::with_fn(db, function), function.data(db).has_self_param())
         }
         FnCallNode::MacroCallExpr(expr) => {
             let macro_def = analyzer.resolve_macro_call(db, &expr)?;
diff --git a/crates/ra_ide_api/src/change.rs b/crates/ra_ide_api/src/change.rs
index 8a05b287f7..3c607d5b53 100644
--- a/crates/ra_ide_api/src/change.rs
+++ b/crates/ra_ide_api/src/change.rs
@@ -313,7 +313,7 @@ impl RootDatabase {
             hir::db::RawItemsQuery
             hir::db::CrateDefMapQuery
             hir::db::GenericParamsQuery
-            hir::db::FunctionDataQuery
+            hir::db::FnDataQuery
             hir::db::TypeAliasDataQuery
             hir::db::ConstDataQuery
             hir::db::StaticDataQuery
diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs
index 5a3f9b5f64..4e2c497e1d 100644
--- a/crates/ra_ide_api/src/completion/complete_dot.rs
+++ b/crates/ra_ide_api/src/completion/complete_dot.rs
@@ -59,7 +59,8 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty)
 fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) {
     let mut seen_methods = FxHashSet::default();
     ctx.analyzer.iterate_method_candidates(ctx.db, receiver, None, |_ty, func| {
-        if func.has_self_param(ctx.db) && seen_methods.insert(func.name(ctx.db)) {
+        let data = func.data(ctx.db);
+        if data.has_self_param() && seen_methods.insert(data.name().clone()) {
             acc.add_function(ctx, func);
         }
         None::<()>
diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs
index 802c7701a3..5d974cf6d5 100644
--- a/crates/ra_ide_api/src/completion/complete_path.rs
+++ b/crates/ra_ide_api/src/completion/complete_path.rs
@@ -53,7 +53,8 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
             ctx.analyzer.iterate_path_candidates(ctx.db, ty.clone(), None, |_ty, item| {
                 match item {
                     hir::AssocItem::Function(func) => {
-                        if !func.has_self_param(ctx.db) {
+                        let data = func.data(ctx.db);
+                        if !data.has_self_param() {
                             acc.add_function(ctx, func);
                         }
                     }
@@ -79,7 +80,8 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
             for item in t.items(ctx.db) {
                 match item {
                     hir::AssocItem::Function(func) => {
-                        if !func.has_self_param(ctx.db) {
+                        let data = func.data(ctx.db);
+                        if !data.has_self_param() {
                             acc.add_function(ctx, func);
                         }
                     }
diff --git a/crates/ra_ide_api/src/completion/presentation.rs b/crates/ra_ide_api/src/completion/presentation.rs
index 896ad15173..bd464d193e 100644
--- a/crates/ra_ide_api/src/completion/presentation.rs
+++ b/crates/ra_ide_api/src/completion/presentation.rs
@@ -199,17 +199,14 @@ impl Completions {
         name: Option<String>,
         func: hir::Function,
     ) {
-        let func_name = func.name(ctx.db);
-        let has_self_param = func.has_self_param(ctx.db);
-        let params = func.params(ctx.db);
-
-        let name = name.unwrap_or_else(|| func_name.to_string());
+        let data = func.data(ctx.db);
+        let name = name.unwrap_or_else(|| data.name().to_string());
         let ast_node = func.source(ctx.db).value;
         let detail = function_label(&ast_node);
 
         let mut builder =
             CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.clone())
-                .kind(if has_self_param {
+                .kind(if data.has_self_param() {
                     CompletionItemKind::Method
                 } else {
                     CompletionItemKind::Function
@@ -224,11 +221,12 @@ impl Completions {
             && ctx.db.feature_flags.get("completion.insertion.add-call-parenthesis")
         {
             tested_by!(inserts_parens_for_function_calls);
-            let (snippet, label) = if params.is_empty() || has_self_param && params.len() == 1 {
-                (format!("{}()$0", func_name), format!("{}()", name))
-            } else {
-                (format!("{}($0)", func_name), format!("{}(…)", name))
-            };
+            let (snippet, label) =
+                if data.params().is_empty() || data.has_self_param() && data.params().len() == 1 {
+                    (format!("{}()$0", data.name()), format!("{}()", name))
+                } else {
+                    (format!("{}($0)", data.name()), format!("{}(…)", name))
+                };
             builder = builder.lookup_by(name).label(label).insert_snippet(snippet);
         }
 


Test patch:
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 74c12a0a2d..b4bdd81f64 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -4857,3 +4857,22 @@ fn main() {
     "###
     );
 }
+
+#[test]
+fn infer_builtin_macros_file() {
+    assert_snapshot!(
+        infer(r#"
+#[rustc_builtin_macro]
+macro_rules! file {() => {}}
+
+fn main() {
+    let x = file!();
+}
+"#),
+        @r###"
+    ![0; 2) '""': &str
+    [64; 88) '{     ...!(); }': ()
+    [74; 75) 'x': &str
+    "###
+    );
+}