Repository: rust-analyzer/rust-analyzer
Pull request #2173 (2019-11-04 15:26:45)

MBE: Add TokenId shift in macro_rules
As discussed in #2169 , for fixing duplication TokenId during expansion :

> What we can do here is to re-number the tokens during expansion. Specifically:
> * when we create macro_rules, we note the highest id of the token we have as shift>
> * when we expand macro rules, if we need to output a token from definition, we just re-use its id
> * if we need to output a token from the argument, we increase its id by shift (so it's guaranteed to not to collide with anything from the definition)
> * finally, when we have a HirFileId of the expansion, we can look up the original value of shift and classify node to the arg/def by comparing it's id with shift.
> 

This PR implement first 3 points of above solution. 


Patch:
diff --git a/.gitattributes b/.gitattributes
index 183e9b5211..a77342d724 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,2 +1,1 @@
-crates/ra_syntax/test_data/** -text eof=LF
-crates/ra_ide_api/src/snapshots/** -text eof=LF
+crates/ra_syntax/tests/data/** -text
diff --git a/Cargo.lock b/Cargo.lock
index 3879204d9e..29f77044e8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -985,7 +985,6 @@ dependencies = [
  "relative-path 1.0.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.13.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "test_utils 0.1.0",
 ]
 
 [[package]]
@@ -1019,6 +1018,7 @@ dependencies = [
  "ra_prof 0.1.0",
  "ra_syntax 0.1.0",
  "ra_tt 0.1.0",
+ "relative-path 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "test_utils 0.1.0",
 ]
@@ -1027,7 +1027,6 @@ dependencies = [
 name = "ra_hir_def"
 version = "0.1.0"
 dependencies = [
- "insta 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "ra_arena 0.1.0",
@@ -1038,6 +1037,7 @@ dependencies = [
  "ra_prof 0.1.0",
  "ra_syntax 0.1.0",
  "ra_tt 0.1.0",
+ "relative-path 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "test_utils 0.1.0",
 ]
@@ -1077,6 +1077,7 @@ dependencies = [
  "ra_text_edit 0.1.0",
  "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "relative-path 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "superslice 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "test_utils 0.1.0",
diff --git a/crates/ra_assists/src/assists/early_return.rs b/crates/ra_assists/src/assists/early_return.rs
index 570a07a20c..ad6c5695a3 100644
--- a/crates/ra_assists/src/assists/early_return.rs
+++ b/crates/ra_assists/src/assists/early_return.rs
@@ -3,10 +3,9 @@ use std::ops::RangeInclusive;
 use hir::db::HirDatabase;
 use ra_syntax::{
     algo::replace_children,
-    ast::{self, edit::IndentLevel, make, Block, Pat::TupleStructPat},
+    ast::{self, edit::IndentLevel, make},
     AstNode,
     SyntaxKind::{FN_DEF, LOOP_EXPR, L_CURLY, R_CURLY, WHILE_EXPR, WHITESPACE},
-    SyntaxNode,
 };
 
 use crate::{
@@ -38,23 +37,7 @@ use crate::{
 // ```
 pub(crate) fn convert_to_guarded_return(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
     let if_expr: ast::IfExpr = ctx.find_node_at_offset()?;
-    let cond = if_expr.condition()?;
-    let mut if_let_ident: Option<String> = None;
-
-    // Check if there is an IfLet that we can handle.
-    match cond.pat() {
-        None => {} // No IfLet, supported.
-        Some(TupleStructPat(ref pat)) if pat.args().count() == 1usize => match &pat.path() {
-            Some(p) => match p.qualifier() {
-                None => if_let_ident = Some(p.syntax().text().to_string()),
-                _ => return None,
-            },
-            _ => return None,
-        },
-        _ => return None, // Unsupported IfLet.
-    };
-
-    let expr = cond.expr()?;
+    let expr = if_expr.condition()?.expr()?;
     let then_block = if_expr.then_branch()?.block()?;
     if if_expr.else_branch().is_some() {
         return None;
@@ -80,8 +63,8 @@ pub(crate) fn convert_to_guarded_return(ctx: AssistCtx<impl HirDatabase>) -> Opt
     let parent_container = parent_block.syntax().parent()?.parent()?;
 
     let early_expression = match parent_container.kind() {
-        WHILE_EXPR | LOOP_EXPR => Some("continue"),
-        FN_DEF => Some("return"),
+        WHILE_EXPR | LOOP_EXPR => Some("continue;"),
+        FN_DEF => Some("return;"),
         _ => None,
     }?;
 
@@ -94,58 +77,34 @@ pub(crate) fn convert_to_guarded_return(ctx: AssistCtx<impl HirDatabase>) -> Opt
 
     ctx.add_assist(AssistId("convert_to_guarded_return"), "convert to guarded return", |edit| {
         let if_indent_level = IndentLevel::from_node(&if_expr.syntax());
-        let new_block = match if_let_ident {
-            None => {
-                // If.
-                let early_expression = &(early_expression.to_owned() + ";");
-                let new_expr =
-                    if_indent_level.increase_indent(make::if_expression(&expr, early_expression));
-                replace(new_expr, &then_block, &parent_block, &if_expr)
-            }
-            Some(if_let_ident) => {
-                // If-let.
-                let new_expr = if_indent_level.increase_indent(make::let_match_early(
-                    expr,
-                    &if_let_ident,
-                    early_expression,
-                ));
-                replace(new_expr, &then_block, &parent_block, &if_expr)
-            }
-        };
+        let new_if_expr =
+            if_indent_level.increase_indent(make::if_expression(&expr, early_expression));
+        let then_block_items = IndentLevel::from(1).decrease_indent(then_block.clone());
+        let end_of_then = then_block_items.syntax().last_child_or_token().unwrap();
+        let end_of_then =
+            if end_of_then.prev_sibling_or_token().map(|n| n.kind()) == Some(WHITESPACE) {
+                end_of_then.prev_sibling_or_token().unwrap()
+            } else {
+                end_of_then
+            };
+        let mut new_if_and_then_statements = new_if_expr.syntax().children_with_tokens().chain(
+            then_block_items
+                .syntax()
+                .children_with_tokens()
+                .skip(1)
+                .take_while(|i| *i != end_of_then),
+        );
+        let new_block = replace_children(
+            &parent_block.syntax(),
+            RangeInclusive::new(
+                if_expr.clone().syntax().clone().into(),
+                if_expr.syntax().clone().into(),
+            ),
+            &mut new_if_and_then_statements,
+        );
         edit.target(if_expr.syntax().text_range());
         edit.replace_ast(parent_block, ast::Block::cast(new_block).unwrap());
         edit.set_cursor(cursor_position);
-
-        fn replace(
-            new_expr: impl AstNode,
-            then_block: &Block,
-            parent_block: &Block,
-            if_expr: &ast::IfExpr,
-        ) -> SyntaxNode {
-            let then_block_items = IndentLevel::from(1).decrease_indent(then_block.clone());
-            let end_of_then = then_block_items.syntax().last_child_or_token().unwrap();
-            let end_of_then =
-                if end_of_then.prev_sibling_or_token().map(|n| n.kind()) == Some(WHITESPACE) {
-                    end_of_then.prev_sibling_or_token().unwrap()
-                } else {
-                    end_of_then
-                };
-            let mut then_statements = new_expr.syntax().children_with_tokens().chain(
-                then_block_items
-                    .syntax()
-                    .children_with_tokens()
-                    .skip(1)
-                    .take_while(|i| *i != end_of_then),
-            );
-            replace_children(
-                &parent_block.syntax(),
-                RangeInclusive::new(
-                    if_expr.clone().syntax().clone().into(),
-                    if_expr.syntax().clone().into(),
-                ),
-                &mut then_statements,
-            )
-        }
     })
 }
 
@@ -184,68 +143,6 @@ mod tests {
         );
     }
 
-    #[test]
-    fn convert_let_inside_fn() {
-        check_assist(
-            convert_to_guarded_return,
-            r#"
-            fn main(n: Option<String>) {
-                bar();
-                if<|> let Some(n) = n {
-                    foo(n);
-
-                    //comment
-                    bar();
-                }
-            }
-            "#,
-            r#"
-            fn main(n: Option<String>) {
-                bar();
-                le<|>t n = match n {
-                    Some(it) => it,
-                    None => return,
-                };
-                foo(n);
-
-                //comment
-                bar();
-            }
-            "#,
-        );
-    }
-
-    #[test]
-    fn convert_let_ok_inside_fn() {
-        check_assist(
-            convert_to_guarded_return,
-            r#"
-            fn main(n: Option<String>) {
-                bar();
-                if<|> let Ok(n) = n {
-                    foo(n);
-
-                    //comment
-                    bar();
-                }
-            }
-            "#,
-            r#"
-            fn main(n: Option<String>) {
-                bar();
-                le<|>t n = match n {
-                    Ok(it) => it,
-                    None => return,
-                };
-                foo(n);
-
-                //comment
-                bar();
-            }
-            "#,
-        );
-    }
-
     #[test]
     fn convert_inside_while() {
         check_assist(
@@ -274,35 +171,6 @@ mod tests {
         );
     }
 
-    #[test]
-    fn convert_let_inside_while() {
-        check_assist(
-            convert_to_guarded_return,
-            r#"
-            fn main() {
-                while true {
-                    if<|> let Some(n) = n {
-                        foo(n);
-                        bar();
-                    }
-                }
-            }
-            "#,
-            r#"
-            fn main() {
-                while true {
-                    le<|>t n = match n {
-                        Some(it) => it,
-                        None => continue,
-                    };
-                    foo(n);
-                    bar();
-                }
-            }
-            "#,
-        );
-    }
-
     #[test]
     fn convert_inside_loop() {
         check_assist(
@@ -331,35 +199,6 @@ mod tests {
         );
     }
 
-    #[test]
-    fn convert_let_inside_loop() {
-        check_assist(
-            convert_to_guarded_return,
-            r#"
-            fn main() {
-                loop {
-                    if<|> let Some(n) = n {
-                        foo(n);
-                        bar();
-                    }
-                }
-            }
-            "#,
-            r#"
-            fn main() {
-                loop {
-                    le<|>t n = match n {
-                        Some(it) => it,
-                        None => continue,
-                    };
-                    foo(n);
-                    bar();
-                }
-            }
-            "#,
-        );
-    }
-
     #[test]
     fn ignore_already_converted_if() {
         check_assist_not_applicable(
diff --git a/crates/ra_db/Cargo.toml b/crates/ra_db/Cargo.toml
index bf1f7920c5..3394ae8ce6 100644
--- a/crates/ra_db/Cargo.toml
+++ b/crates/ra_db/Cargo.toml
@@ -12,4 +12,3 @@ rustc-hash = "1.0"
 ra_syntax = { path = "../ra_syntax" }
 ra_cfg = { path = "../ra_cfg" }
 ra_prof = { path = "../ra_prof" }
-test_utils = { path = "../test_utils" }
diff --git a/crates/ra_db/src/fixture.rs b/crates/ra_db/src/fixture.rs
deleted file mode 100644
index f5dd59f840..0000000000
--- a/crates/ra_db/src/fixture.rs
+++ /dev/null
@@ -1,186 +0,0 @@
-//! FIXME: write short doc here
-
-use std::sync::Arc;
-
-use ra_cfg::CfgOptions;
-use rustc_hash::FxHashMap;
-use test_utils::{extract_offset, parse_fixture, CURSOR_MARKER};
-
-use crate::{
-    CrateGraph, Edition, FileId, FilePosition, RelativePathBuf, SourceDatabaseExt, SourceRoot,
-    SourceRootId,
-};
-
-pub const WORKSPACE: SourceRootId = SourceRootId(0);
-
-pub trait WithFixture: Default + SourceDatabaseExt + 'static {
-    fn with_single_file(text: &str) -> (Self, FileId) {
-        let mut db = Self::default();
-        let file_id = with_single_file(&mut db, text);
-        (db, file_id)
-    }
-
-    fn with_files(fixture: &str) -> Self {
-        let mut db = Self::default();
-        let pos = with_files(&mut db, fixture);
-        assert!(pos.is_none());
-        db
-    }
-
-    fn with_position(fixture: &str) -> (Self, FilePosition) {
-        let mut db = Self::default();
-        let pos = with_files(&mut db, fixture);
-        (db, pos.unwrap())
-    }
-}
-
-impl<DB: SourceDatabaseExt + Default + 'static> WithFixture for DB {}
-
-fn with_single_file(db: &mut dyn SourceDatabaseExt, text: &str) -> FileId {
-    let file_id = FileId(0);
-    let rel_path: RelativePathBuf = "/main.rs".into();
-
-    let mut source_root = SourceRoot::default();
-    source_root.insert_file(rel_path.clone(), file_id);
-
-    let mut crate_graph = CrateGraph::default();
-    crate_graph.add_crate_root(file_id, Edition::Edition2018, CfgOptions::default());
-
-    db.set_file_text(file_id, Arc::new(text.to_string()));
-    db.set_file_relative_path(file_id, rel_path);
-    db.set_file_source_root(file_id, WORKSPACE);
-    db.set_source_root(WORKSPACE, Arc::new(source_root));
-    db.set_crate_graph(Arc::new(crate_graph));
-
-    file_id
-}
-
-fn with_files(db: &mut dyn SourceDatabaseExt, fixture: &str) -> Option<FilePosition> {
-    let fixture = parse_fixture(fixture);
-
-    let mut crate_graph = CrateGraph::default();
-    let mut crates = FxHashMap::default();
-    let mut crate_deps = Vec::new();
-    let mut default_crate_root: Option<FileId> = None;
-
-    let mut source_root = SourceRoot::default();
-    let mut source_root_id = WORKSPACE;
-    let mut source_root_prefix: RelativePathBuf = "/".into();
-    let mut file_id = FileId(0);
-
-    let mut file_position = None;
-
-    for entry in fixture.iter() {
-        let meta = match parse_meta(&entry.meta) {
-            ParsedMeta::Root { path } => {
-                let source_root = std::mem::replace(&mut source_root, SourceRoot::default());
-                db.set_source_root(source_root_id, Arc::new(source_root));
-                source_root_id.0 += 1;
-                source_root_prefix = path;
-                continue;
-            }
-            ParsedMeta::File(it) => it,
-        };
-        assert!(meta.path.starts_with(&source_root_prefix));
-
-        if let Some(krate) = meta.krate {
-            let crate_id = crate_graph.add_crate_root(file_id, meta.edition, meta.cfg);
-            let prev = crates.insert(krate.clone(), crate_id);
-            assert!(prev.is_none());
-            for dep in meta.deps {
-                crate_deps.push((krate.clone(), dep))
-            }
-        } else if meta.path == "/main.rs" || meta.path == "/lib.rs" {
-            assert!(default_crate_root.is_none());
-            default_crate_root = Some(file_id);
-        }
-
-        let text = if entry.text.contains(CURSOR_MARKER) {
-            let (offset, text) = extract_offset(&entry.text);
-            assert!(file_position.is_none());
-            file_position = Some(FilePosition { file_id, offset });
-            text.to_string()
-        } else {
-            entry.text.to_string()
-        };
-
-        db.set_file_text(file_id, Arc::new(text));
-        db.set_file_relative_path(file_id, meta.path.clone());
-        db.set_file_source_root(file_id, source_root_id);
-        source_root.insert_file(meta.path, file_id);
-
-        file_id.0 += 1;
-    }
-
-    if crates.is_empty() {
-        let crate_root = default_crate_root.unwrap();
-        crate_graph.add_crate_root(crate_root, Edition::Edition2018, CfgOptions::default());
-    } else {
-        for (from, to) in crate_deps {
-            let from_id = crates[&from];
-            let to_id = crates[&to];
-            crate_graph.add_dep(from_id, to.into(), to_id).unwrap();
-        }
-    }
-
-    db.set_source_root(source_root_id, Arc::new(source_root));
-    db.set_crate_graph(Arc::new(crate_graph));
-
-    file_position
-}
-
-enum ParsedMeta {
-    Root { path: RelativePathBuf },
-    File(FileMeta),
-}
-
-struct FileMeta {
-    path: RelativePathBuf,
-    krate: Option<String>,
-    deps: Vec<String>,
-    cfg: CfgOptions,
-    edition: Edition,
-}
-
-//- /lib.rs crate:foo deps:bar,baz
-fn parse_meta(meta: &str) -> ParsedMeta {
-    let components = meta.split_ascii_whitespace().collect::<Vec<_>>();
-
-    if components[0] == "root" {
-        let path: RelativePathBuf = components[1].into();
-        assert!(path.starts_with("/") && path.ends_with("/"));
-        return ParsedMeta::Root { path };
-    }
-
-    let path: RelativePathBuf = components[0].into();
-    assert!(path.starts_with("/"));
-
-    let mut krate = None;
-    let mut deps = Vec::new();
-    let mut edition = Edition::Edition2018;
-    let mut cfg = CfgOptions::default();
-    for component in components[1..].iter() {
-        let (key, value) = split1(component, ':').unwrap();
-        match key {
-            "crate" => krate = Some(value.to_string()),
-            "deps" => deps = value.split(',').map(|it| it.to_string()).collect(),
-            "edition" => edition = Edition::from_string(&value),
-            "cfg" => {
-                for key in value.split(',') {
-                    match split1(key, '=') {
-                        None => cfg.insert_atom(key.into()),
-                        Some((k, v)) => cfg.insert_key_value(k.into(), v.into()),
-                    }
-                }
-            }
-            _ => panic!("bad component: {:?}", component),
-        }
-    }
-
-    ParsedMeta::File(FileMeta { path, krate, deps, edition, cfg })
-}
-
-fn split1(haystack: &str, delim: char) -> Option<(&str, &str)> {
-    let idx = haystack.find(delim)?;
-    Some((&haystack[..idx], &haystack[idx + delim.len_utf8()..]))
-}
diff --git a/crates/ra_db/src/input.rs b/crates/ra_db/src/input.rs
index 60f7dc8815..eafa95921c 100644
--- a/crates/ra_db/src/input.rs
+++ b/crates/ra_db/src/input.rs
@@ -6,14 +6,13 @@
 //! actual IO. See `vfs` and `project_model` in the `ra_lsp_server` crate for how
 //! actual IO is done and lowered to input.
 
+use relative_path::{RelativePath, RelativePathBuf};
 use rustc_hash::FxHashMap;
 
 use ra_cfg::CfgOptions;
 use ra_syntax::SmolStr;
 use rustc_hash::FxHashSet;
 
-use crate::{RelativePath, RelativePathBuf};
-
 /// `FileId` is an integer which uniquely identifies a file. File paths are
 /// messy and system-dependent, so most of the code should work directly with
 /// `FileId`, without inspecting the path. The mapping between `FileId` and path
@@ -98,7 +97,6 @@ pub enum Edition {
 }
 
 impl Edition {
-    //FIXME: replace with FromStr with proper error handling
     pub fn from_string(s: &str) -> Edition {
         match s {
             "2015" => Edition::Edition2015,
diff --git a/crates/ra_db/src/lib.rs b/crates/ra_db/src/lib.rs
index b6bfd531de..0d1ab48438 100644
--- a/crates/ra_db/src/lib.rs
+++ b/crates/ra_db/src/lib.rs
@@ -1,18 +1,17 @@
 //! ra_db defines basic database traits. The concrete DB is defined by ra_ide_api.
 mod cancellation;
 mod input;
-pub mod fixture;
 
 use std::{panic, sync::Arc};
 
 use ra_prof::profile;
 use ra_syntax::{ast, Parse, SourceFile, TextRange, TextUnit};
+use relative_path::{RelativePath, RelativePathBuf};
 
 pub use crate::{
     cancellation::Canceled,
     input::{CrateGraph, CrateId, Dependency, Edition, FileId, SourceRoot, SourceRootId},
 };
-pub use relative_path::{RelativePath, RelativePathBuf};
 pub use salsa;
 
 pub trait CheckCanceled {
diff --git a/crates/ra_hir/Cargo.toml b/crates/ra_hir/Cargo.toml
index 3249613284..fae5dc7cb5 100644
--- a/crates/ra_hir/Cargo.toml
+++ b/crates/ra_hir/Cargo.toml
@@ -7,6 +7,7 @@ authors = ["rust-analyzer developers"]
 [dependencies]
 arrayvec = "0.5.1"
 log = "0.4.5"
+relative-path = "1.0.0"
 rustc-hash = "1.0"
 parking_lot = "0.9.0"
 ena = "0.13"
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 181c5d47af..5b78bdfef3 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -9,7 +9,7 @@ use hir_def::{
     adt::VariantData,
     builtin_type::BuiltinType,
     type_ref::{Mutability, TypeRef},
-    CrateModuleId, LocalEnumVariantId, LocalStructFieldId, ModuleId, UnionId,
+    CrateModuleId, LocalEnumVariantId, LocalStructFieldId, ModuleId,
 };
 use hir_expand::{
     diagnostics::DiagnosticSink,
@@ -28,10 +28,11 @@ use crate::{
         TypeAliasId,
     },
     impl_block::ImplBlock,
+    nameres::{ImportId, ModuleScope, Namespace},
     resolve::{Resolver, Scope, TypeNs},
     traits::TraitData,
     ty::{InferenceResult, TraitRef},
-    Either, HasSource, Name, ScopeDef, Ty, {ImportId, Namespace},
+    Either, HasSource, Name, Ty,
 };
 
 /// hir::Crate describes a single crate. It's the main interface with which
@@ -65,7 +66,7 @@ impl Crate {
     }
 
     pub fn root_module(self, db: &impl DefDatabase) -> Option<Module> {
-        let module_id = db.crate_def_map(self.crate_id).root();
+        let module_id = db.crate_def_map(self).root();
         Some(Module::new(self, module_id))
     }
 
@@ -119,7 +120,7 @@ impl Module {
 
     /// Name of this module.
     pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
-        let def_map = db.crate_def_map(self.id.krate);
+        let def_map = db.crate_def_map(self.krate());
         let parent = def_map[self.id.module_id].parent?;
         def_map[parent].children.iter().find_map(|(name, module_id)| {
             if *module_id == self.id.module_id {
@@ -150,20 +151,20 @@ impl Module {
     /// might be missing `krate`. This can happen if a module's file is not included
     /// in the module tree of any target in `Cargo.toml`.
     pub fn crate_root(self, db: &impl DefDatabase) -> Module {
-        let def_map = db.crate_def_map(self.id.krate);
+        let def_map = db.crate_def_map(self.krate());
         self.with_module_id(def_map.root())
     }
 
     /// Finds a child module with the specified name.
     pub fn child(self, db: &impl HirDatabase, name: &Name) -> Option<Module> {
-        let def_map = db.crate_def_map(self.id.krate);
+        let def_map = db.crate_def_map(self.krate());
         let child_id = def_map[self.id.module_id].children.get(name)?;
         Some(self.with_module_id(*child_id))
     }
 
     /// Iterates over all child modules.
     pub fn children(self, db: &impl DefDatabase) -> impl Iterator<Item = Module> {
-        let def_map = db.crate_def_map(self.id.krate);
+        let def_map = db.crate_def_map(self.krate());
         let children = def_map[self.id.module_id]
             .children
             .iter()
@@ -174,7 +175,7 @@ impl Module {
 
     /// Finds a parent module.
     pub fn parent(self, db: &impl DefDatabase) -> Option<Module> {
-        let def_map = db.crate_def_map(self.id.krate);
+        let def_map = db.crate_def_map(self.krate());
         let parent_id = def_map[self.id.module_id].parent?;
         Some(self.with_module_id(parent_id))
     }
@@ -190,16 +191,12 @@ impl Module {
     }
 
     /// Returns a `ModuleScope`: a set of items, visible in this module.
-    pub fn scope(self, db: &impl HirDatabase) -> Vec<(Name, ScopeDef, Option<ImportId>)> {
-        db.crate_def_map(self.id.krate)[self.id.module_id]
-            .scope
-            .entries()
-            .map(|(name, res)| (name.clone(), res.def.into(), res.import))
-            .collect()
+    pub fn scope(self, db: &impl HirDatabase) -> ModuleScope {
+        db.crate_def_map(self.krate())[self.id.module_id].scope.clone()
     }
 
     pub fn diagnostics(self, db: &impl HirDatabase, sink: &mut DiagnosticSink) {
-        db.crate_def_map(self.id.krate).add_diagnostics(db, self.id.module_id, sink);
+        db.crate_def_map(self.krate()).add_diagnostics(db, self.id.module_id, sink);
         for decl in self.declarations(db) {
             match decl {
                 crate::ModuleDef::Function(f) => f.diagnostics(db, sink),
@@ -223,12 +220,12 @@ impl Module {
     }
 
     pub(crate) fn resolver(self, db: &impl DefDatabase) -> Resolver {
-        let def_map = db.crate_def_map(self.id.krate);
+        let def_map = db.crate_def_map(self.krate());
         Resolver::default().push_module_scope(def_map, self.id.module_id)
     }
 
     pub fn declarations(self, db: &impl DefDatabase) -> Vec<ModuleDef> {
-        let def_map = db.crate_def_map(self.id.krate);
+        let def_map = db.crate_def_map(self.krate());
         def_map[self.id.module_id]
             .scope
             .entries()
@@ -236,7 +233,6 @@ impl Module {
             .flat_map(|per_ns| {
                 per_ns.take_types().into_iter().chain(per_ns.take_values().into_iter())
             })
-            .map(ModuleDef::from)
             .collect()
     }
 
@@ -340,12 +336,12 @@ impl Struct {
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 pub struct Union {
-    pub(crate) id: UnionId,
+    pub(crate) id: StructId,
 }
 
 impl Union {
     pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
-        db.union_data(self.id).name.clone()
+        db.struct_data(self.id).name.clone()
     }
 
     pub fn module(self, db: &impl HirDatabase) -> Module {
diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs
index 6d116ee75c..bd0c3c226a 100644
--- a/crates/ra_hir/src/code_model/src.rs
+++ b/crates/ra_hir/src/code_model/src.rs
@@ -22,7 +22,7 @@ pub trait HasSource {
 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.id.krate);
+        let def_map = db.crate_def_map(self.krate());
         let decl_id = def_map[self.id.module_id].declaration;
         let file_id = def_map[self.id.module_id].definition;
         let ast = ModuleSource::new(db, file_id, decl_id);
@@ -36,7 +36,7 @@ impl Module {
         self,
         db: &(impl DefDatabase + AstDatabase),
     ) -> Option<Source<ast::Module>> {
-        let def_map = db.crate_def_map(self.id.krate);
+        let def_map = db.crate_def_map(self.krate());
         let decl = def_map[self.id.module_id].declaration?;
         let ast = decl.to_node(db);
         Some(Source { file_id: decl.file_id(), ast })
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index eb66325f7f..89ca4e39f0 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -11,19 +11,20 @@ use crate::{
     ids,
     impl_block::{ImplBlock, ImplSourceMap, ModuleImplBlocks},
     lang_item::{LangItemTarget, LangItems},
+    nameres::{CrateDefMap, Namespace},
     traits::TraitData,
     ty::{
         method_resolution::CrateImplBlocks, traits::Impl, CallableDef, FnSig, GenericPredicate,
         InferenceResult, Substs, Ty, TypableDef, TypeCtor,
     },
     type_alias::TypeAliasData,
-    Const, ConstData, Crate, DefWithBody, ExprScopes, FnData, Function, Module, Namespace, Static,
+    Const, ConstData, Crate, DefWithBody, ExprScopes, FnData, Function, Module, Static,
     StructField, Trait, TypeAlias,
 };
 
 pub use hir_def::db::{
-    CrateDefMapQuery, DefDatabase2, DefDatabase2Storage, EnumDataQuery, InternDatabase,
-    InternDatabaseStorage, RawItemsQuery, RawItemsWithSourceMapQuery, StructDataQuery,
+    DefDatabase2, DefDatabase2Storage, EnumDataQuery, InternDatabase, InternDatabaseStorage,
+    RawItemsQuery, RawItemsWithSourceMapQuery, StructDataQuery,
 };
 pub use hir_expand::db::{
     AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery,
@@ -40,6 +41,9 @@ pub trait DefDatabase: HirDebugDatabase + DefDatabase2 {
     #[salsa::invoke(crate::traits::TraitItemsIndex::trait_items_index)]
     fn trait_items_index(&self, module: Module) -> crate::traits::TraitItemsIndex;
 
+    #[salsa::invoke(CrateDefMap::crate_def_map_query)]
+    fn crate_def_map(&self, krate: Crate) -> Arc<CrateDefMap>;
+
     #[salsa::invoke(ModuleImplBlocks::impls_in_module_with_source_map_query)]
     fn impls_in_module_with_source_map(
         &self,
diff --git a/crates/ra_hir/src/diagnostics.rs b/crates/ra_hir/src/diagnostics.rs
index 1751e7be33..a33af8f467 100644
--- a/crates/ra_hir/src/diagnostics.rs
+++ b/crates/ra_hir/src/diagnostics.rs
@@ -3,10 +3,10 @@
 use std::any::Any;
 
 use ra_syntax::{ast, AstNode, AstPtr, SyntaxNodePtr};
+use relative_path::RelativePathBuf;
 
 use crate::{db::AstDatabase, HirFileId, Name, Source};
 
-pub use hir_def::diagnostics::UnresolvedModule;
 pub use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink};
 
 #[derive(Debug)]
@@ -29,6 +29,25 @@ impl Diagnostic for NoSuchField {
     }
 }
 
+#[derive(Debug)]
+pub struct UnresolvedModule {
+    pub file: HirFileId,
+    pub decl: AstPtr<ast::Module>,
+    pub candidate: RelativePathBuf,
+}
+
+impl Diagnostic for UnresolvedModule {
+    fn message(&self) -> String {
+        "unresolved module".to_string()
+    }
+    fn source(&self) -> Source<SyntaxNodePtr> {
+        Source { file_id: self.file, ast: self.decl.into() }
+    }
+    fn as_any(&self) -> &(dyn Any + Send + 'static) {
+        self
+    }
+}
+
 #[derive(Debug)]
 pub struct MissingFields {
     pub file: HirFileId,
diff --git a/crates/ra_hir/src/from_id.rs b/crates/ra_hir/src/from_id.rs
deleted file mode 100644
index 089dbc9084..0000000000
--- a/crates/ra_hir/src/from_id.rs
+++ /dev/null
@@ -1,63 +0,0 @@
-//! Utility module for converting between hir_def ids and code_model wrappers.
-//!
-//! It's unclear if we need this long-term, but it's definitelly useful while we
-//! are splitting the hir.
-
-use hir_def::{AdtId, EnumVariantId, ModuleDefId};
-
-use crate::{Adt, EnumVariant, ModuleDef};
-
-macro_rules! from_id {
-    ($(($id:path, $ty:path)),*) => {$(
-        impl From<$id> for $ty {
-            fn from(id: $id) -> $ty {
-                $ty { id }
-            }
-        }
-    )*}
-}
-
-from_id![
-    (hir_def::ModuleId, crate::Module),
-    (hir_def::StructId, crate::Struct),
-    (hir_def::UnionId, crate::Union),
-    (hir_def::EnumId, crate::Enum),
-    (hir_def::TypeAliasId, crate::TypeAlias),
-    (hir_def::TraitId, crate::Trait),
-    (hir_def::StaticId, crate::Static),
-    (hir_def::ConstId, crate::Const),
-    (hir_def::FunctionId, crate::Function),
-    (hir_expand::MacroDefId, crate::MacroDef)
-];
-
-impl From<AdtId> for Adt {
-    fn from(id: AdtId) -> Self {
-        match id {
-            AdtId::StructId(it) => Adt::Struct(it.into()),
-            AdtId::UnionId(it) => Adt::Union(it.into()),
-            AdtId::EnumId(it) => Adt::Enum(it.into()),
-        }
-    }
-}
-
-impl From<EnumVariantId> for EnumVariant {
-    fn from(id: EnumVariantId) -> Self {
-        EnumVariant { parent: id.parent.into(), id: id.local_id }
-    }
-}
-
-impl From<ModuleDefId> for ModuleDef {
-    fn from(id: ModuleDefId) -> Self {
-        match id {
-            ModuleDefId::ModuleId(it) => ModuleDef::Module(it.into()),
-            ModuleDefId::FunctionId(it) => ModuleDef::Function(it.into()),
-            ModuleDefId::AdtId(it) => ModuleDef::Adt(it.into()),
-            ModuleDefId::EnumVariantId(it) => ModuleDef::EnumVariant(it.into()),
-            ModuleDefId::ConstId(it) => ModuleDef::Const(it.into()),
-            ModuleDefId::StaticId(it) => ModuleDef::Static(it.into()),
-            ModuleDefId::TraitId(it) => ModuleDef::Trait(it.into()),
-            ModuleDefId::TypeAliasId(it) => ModuleDef::TypeAlias(it.into()),
-            ModuleDefId::BuiltinType(it) => ModuleDef::BuiltinType(it),
-        }
-    }
-}
diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs
index 9899bdbbce..a9de014553 100644
--- a/crates/ra_hir/src/from_source.rs
+++ b/crates/ra_hir/src/from_source.rs
@@ -149,20 +149,14 @@ impl Module {
             ModuleSource::SourceFile(_) => None,
         };
 
-        db.relevant_crates(src.file_id.original_file(db)).iter().find_map(|&crate_id| {
-            let def_map = db.crate_def_map(crate_id);
-
-            let (module_id, _module_data) =
-                def_map.modules.iter().find(|(_module_id, module_data)| {
-                    if decl_id.is_some() {
-                        module_data.declaration == decl_id
-                    } else {
-                        module_data.definition.map(|it| it.into()) == Some(src.file_id)
-                    }
-                })?;
-
-            Some(Module::new(Crate { crate_id }, module_id))
-        })
+        db.relevant_crates(src.file_id.original_file(db))
+            .iter()
+            .map(|&crate_id| Crate { crate_id })
+            .find_map(|krate| {
+                let def_map = db.crate_def_map(krate);
+                let module_id = def_map.find_module_by_source(src.file_id, decl_id)?;
+                Some(Module::new(krate, module_id))
+            })
     }
 }
 
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 3ba99d92d7..0ba17e5710 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -34,6 +34,7 @@ pub mod mock;
 pub mod source_binder;
 
 mod ids;
+mod nameres;
 mod adt;
 mod traits;
 mod type_alias;
@@ -46,7 +47,6 @@ mod resolve;
 pub mod diagnostics;
 mod util;
 
-mod from_id;
 mod code_model;
 
 pub mod from_source;
@@ -72,6 +72,7 @@ pub use crate::{
     generics::{GenericDef, GenericParam, GenericParams, HasGenericParams},
     ids::{HirFileId, MacroCallId, MacroCallLoc, MacroDefId, MacroFile},
     impl_block::ImplBlock,
+    nameres::{ImportId, Namespace, PerNs},
     resolve::ScopeDef,
     source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer},
     ty::{
@@ -81,10 +82,6 @@ pub use crate::{
 
 pub use hir_def::{
     builtin_type::BuiltinType,
-    nameres::{
-        per_ns::{Namespace, PerNs},
-        raw::ImportId,
-    },
     path::{Path, PathKind},
     type_ref::Mutability,
 };
diff --git a/crates/ra_hir/src/marks.rs b/crates/ra_hir/src/marks.rs
index 0d4fa5b673..b423489a11 100644
--- a/crates/ra_hir/src/marks.rs
+++ b/crates/ra_hir/src/marks.rs
@@ -1,10 +1,21 @@
 //! See test_utils/src/marks.rs
 
 test_utils::marks!(
+    bogus_paths
+    // FIXME: restore this mark once hir is split
+    name_res_works_for_broken_modules
+    can_import_enum_variant
     type_var_cycles_resolve_completely
     type_var_cycles_resolve_as_possible
     type_var_resolves_to_int_var
+    glob_enum
+    glob_across_crates
+    std_prelude
     match_ergonomics_ref
     infer_while_let
+    macro_rules_from_other_crates_are_visible_with_macro_use
+    prelude_is_macro_use
     coerce_merge_fail_fallback
+    macro_dollar_crate_self
+    macro_dollar_crate_other
 );
diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs
index ab97a09b91..4c89c8d384 100644
--- a/crates/ra_hir/src/mock.rs
+++ b/crates/ra_hir/src/mock.rs
@@ -7,8 +7,9 @@ use parking_lot::Mutex;
 use ra_cfg::CfgOptions;
 use ra_db::{
     salsa, CrateGraph, CrateId, Edition, FileId, FileLoader, FileLoaderDelegate, FilePosition,
-    RelativePath, RelativePathBuf, SourceDatabase, SourceDatabaseExt, SourceRoot, SourceRootId,
+    SourceDatabase, SourceDatabaseExt, SourceRoot, SourceRootId,
 };
+use relative_path::{RelativePath, RelativePathBuf};
 use rustc_hash::FxHashMap;
 use test_utils::{extract_offset, parse_fixture, CURSOR_MARKER};
 
@@ -77,6 +78,12 @@ impl MockDatabase {
         (db, source_root, file_id)
     }
 
+    pub fn with_position(fixture: &str) -> (MockDatabase, FilePosition) {
+        let (db, position) = MockDatabase::from_fixture(fixture);
+        let position = position.expect("expected a marker ( <|> )");
+        (db, position)
+    }
+
     pub fn file_id_of(&self, path: &str) -> FileId {
         match self.files.get(path) {
             Some(it) => *it,
@@ -84,6 +91,25 @@ impl MockDatabase {
         }
     }
 
+    pub fn set_crate_graph_from_fixture(&mut self, graph: CrateGraphFixture) {
+        let mut ids = FxHashMap::default();
+        let mut crate_graph = CrateGraph::default();
+        for (crate_name, (crate_root, edition, cfg_options, _)) in graph.0.iter() {
+            let crate_root = self.file_id_of(&crate_root);
+            let crate_id = crate_graph.add_crate_root(crate_root, *edition, cfg_options.clone());
+            Arc::make_mut(&mut self.crate_names).insert(crate_id, crate_name.clone());
+            ids.insert(crate_name, crate_id);
+        }
+        for (crate_name, (_, _, _, deps)) in graph.0.iter() {
+            let from = ids[crate_name];
+            for dep in deps {
+                let to = ids[dep];
+                crate_graph.add_dep(from, dep.as_str().into(), to).unwrap();
+            }
+        }
+        self.set_crate_graph(Arc::new(crate_graph))
+    }
+
     pub fn diagnostics(&self) -> String {
         let mut buf = String::new();
         let mut files: Vec<FileId> = self.files.values().copied().collect();
@@ -260,3 +286,46 @@ impl MockDatabase {
             .collect()
     }
 }
+
+#[derive(Default)]
+pub struct CrateGraphFixture(pub Vec<(String, (String, Edition, CfgOptions, Vec<String>))>);
+
+#[macro_export]
+macro_rules! crate_graph {
+    ($(
+        $crate_name:literal: (
+            $crate_path:literal,
+            $($edition:literal,)?
+            [$($dep:literal),*]
+            $(, cfg = {
+                $($key:literal $(= $value:literal)?),*
+                $(,)?
+            })?
+        ),
+    )*) => {{
+        let mut res = $crate::mock::CrateGraphFixture::default();
+        $(
+            #[allow(unused_mut, unused_assignments)]
+            let mut edition = ra_db::Edition::Edition2018;
+            $(edition = ra_db::Edition::from_string($edition);)?
+            let cfg_options = {
+                #[allow(unused_mut)]
+                let mut cfg = ::ra_cfg::CfgOptions::default();
+                $(
+                    $(
+                        if 0 == 0 $(+ { drop($value); 1})? {
+                            cfg.insert_atom($key.into());
+                        }
+                        $(cfg.insert_key_value($key.into(), $value.into());)?
+                    )*
+                )?
+                cfg
+            };
+            res.0.push((
+                $crate_name.to_string(),
+                ($crate_path.to_string(), edition, cfg_options, vec![$($dep.to_string()),*])
+            ));
+        )*
+        res
+    }}
+}
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs
new file mode 100644
index 0000000000..32a6ab4749
--- /dev/null
+++ b/crates/ra_hir/src/nameres.rs
@@ -0,0 +1,558 @@
+//! This module implements import-resolution/macro expansion algorithm.
+//!
+//! The result of this module is `CrateDefMap`: a data structure which contains:
+//!
+//!   * a tree of modules for the crate
+//!   * for each module, a set of items visible in the module (directly declared
+//!     or imported)
+//!
+//! Note that `CrateDefMap` contains fully macro expanded code.
+//!
+//! Computing `CrateDefMap` can be partitioned into several logically
+//! independent "phases". The phases are mutually recursive though, there's no
+//! strict ordering.
+//!
+//! ## Collecting RawItems
+//!
+//!  This happens in the `raw` module, which parses a single source file into a
+//!  set of top-level items. Nested imports are desugared to flat imports in
+//!  this phase. Macro calls are represented as a triple of (Path, Option<Name>,
+//!  TokenTree).
+//!
+//! ## Collecting Modules
+//!
+//! This happens in the `collector` module. In this phase, we recursively walk
+//! tree of modules, collect raw items from submodules, populate module scopes
+//! with defined items (so, we assign item ids in this phase) and record the set
+//! of unresolved imports and macros.
+//!
+//! While we walk tree of modules, we also record macro_rules definitions and
+//! expand calls to macro_rules defined macros.
+//!
+//! ## Resolving Imports
+//!
+//! We maintain a list of currently unresolved imports. On every iteration, we
+//! try to resolve some imports from this list. If the import is resolved, we
+//! record it, by adding an item to current module scope and, if necessary, by
+//! recursively populating glob imports.
+//!
+//! ## Resolving Macros
+//!
+//! macro_rules from the same crate use a global mutable namespace. We expand
+//! them immediately, when we collect modules.
+//!
+//! Macros from other crates (including proc-macros) can be used with
+//! `foo::bar!` syntax. We handle them similarly to imports. There's a list of
+//! unexpanded macros. On every iteration, we try to resolve each macro call
+//! path and, upon success, we run macro expansion and "collect module" phase
+//! on the result
+
+mod per_ns;
+mod collector;
+#[cfg(test)]
+mod tests;
+
+use std::sync::Arc;
+
+use hir_def::{builtin_type::BuiltinType, CrateModuleId};
+use hir_expand::diagnostics::DiagnosticSink;
+use once_cell::sync::Lazy;
+use ra_arena::Arena;
+use ra_db::{Edition, FileId};
+use ra_prof::profile;
+use ra_syntax::ast;
+use rustc_hash::{FxHashMap, FxHashSet};
+use test_utils::tested_by;
+
+use crate::{
+    db::{AstDatabase, DefDatabase},
+    ids::MacroDefId,
+    nameres::diagnostics::DefDiagnostic,
+    Adt, AstId, Crate, HirFileId, MacroDef, Module, ModuleDef, Name, Path, PathKind, Trait,
+};
+
+pub use self::per_ns::{Namespace, PerNs};
+
+pub use hir_def::nameres::raw::ImportId;
+
+/// Contains all top-level defs from a macro-expanded crate
+#[derive(Debug, PartialEq, Eq)]
+pub struct CrateDefMap {
+    krate: Crate,
+    edition: Edition,
+    /// The prelude module for this crate. This either comes from an import
+    /// marked with the `prelude_import` attribute, or (in the normal case) from
+    /// a dependency (`std` or `core`).
+    prelude: Option<Module>,
+    extern_prelude: FxHashMap<Name, ModuleDef>,
+    root: CrateModuleId,
+    modules: Arena<CrateModuleId, ModuleData>,
+
+    /// Some macros are not well-behavior, which leads to infinite loop
+    /// e.g. macro_rules! foo { ($ty:ty) => { foo!($ty); } }
+    /// We mark it down and skip it in collector
+    ///
+    /// FIXME:
+    /// Right now it only handle a poison macro in a single crate,
+    /// such that if other crate try to call that macro,
+    /// the whole process will do again until it became poisoned in that crate.
+    /// We should handle this macro set globally
+    /// However, do we want to put it as a global variable?
+    poison_macros: FxHashSet<MacroDefId>,
+
+    diagnostics: Vec<DefDiagnostic>,
+}
+
+impl std::ops::Index<CrateModuleId> for CrateDefMap {
+    type Output = ModuleData;
+    fn index(&self, id: CrateModuleId) -> &ModuleData {
+        &self.modules[id]
+    }
+}
+
+#[derive(Default, Debug, PartialEq, Eq)]
+pub struct ModuleData {
+    pub(crate) parent: Option<CrateModuleId>,
+    pub(crate) children: FxHashMap<Name, CrateModuleId>,
+    pub(crate) scope: ModuleScope,
+    /// None for root
+    pub(crate) declaration: Option<AstId<ast::Module>>,
+    /// None for inline modules.
+    ///
+    /// Note that non-inline modules, by definition, live inside non-macro file.
+    pub(crate) definition: Option<FileId>,
+}
+
+#[derive(Debug, Default, PartialEq, Eq, Clone)]
+pub struct ModuleScope {
+    items: FxHashMap<Name, Resolution>,
+    /// Macros visable in current module in legacy textual scope
+    ///
+    /// For macros invoked by an unquatified identifier like `bar!()`, `legacy_macros` will be searched in first.
+    /// If it yields no result, then it turns to module scoped `macros`.
+    /// It macros with name quatified with a path like `crate::foo::bar!()`, `legacy_macros` will be skipped,
+    /// and only normal scoped `macros` will be searched in.
+    ///
+    /// Note that this automatically inherit macros defined textually before the definition of module itself.
+    ///
+    /// Module scoped macros will be inserted into `items` instead of here.
+    // FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will
+    // be all resolved to the last one defined if shadowing happens.
+    legacy_macros: FxHashMap<Name, MacroDef>,
+}
+
+static BUILTIN_SCOPE: Lazy<FxHashMap<Name, Resolution>> = Lazy::new(|| {
+    BuiltinType::ALL
+        .iter()
+        .map(|(name, ty)| {
+            (name.clone(), Resolution { def: PerNs::types(ty.clone().into()), import: None })
+        })
+        .collect()
+});
+
+/// Legacy macros can only be accessed through special methods like `get_legacy_macros`.
+/// Other methods will only resolve values, types and module scoped macros only.
+impl ModuleScope {
+    pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a Name, &'a Resolution)> + 'a {
+        //FIXME: shadowing
+        self.items.iter().chain(BUILTIN_SCOPE.iter())
+    }
+
+    /// Iterate over all module scoped macros
+    pub fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDef)> + 'a {
+        self.items
+            .iter()
+            .filter_map(|(name, res)| res.def.get_macros().map(|macro_| (name, macro_)))
+    }
+
+    /// Iterate over all legacy textual scoped macros visable at the end of the module
+    pub fn legacy_macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDef)> + 'a {
+        self.legacy_macros.iter().map(|(name, def)| (name, *def))
+    }
+
+    /// Get a name from current module scope, legacy macros are not included
+    pub fn get(&self, name: &Name) -> Option<&Resolution> {
+        self.items.get(name).or_else(|| BUILTIN_SCOPE.get(name))
+    }
+
+    pub fn traits<'a>(&'a self) -> impl Iterator<Item = Trait> + 'a {
+        self.items.values().filter_map(|r| match r.def.take_types() {
+            Some(ModuleDef::Trait(t)) => Some(t),
+            _ => None,
+        })
+    }
+
+    fn get_legacy_macro(&self, name: &Name) -> Option<MacroDef> {
+        self.legacy_macros.get(name).copied()
+    }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Default)]
+pub struct Resolution {
+    /// None for unresolved
+    pub def: PerNs,
+    /// ident by which this is imported into local scope.
+    pub import: Option<ImportId>,
+}
+
+impl Resolution {
+    pub(crate) fn from_macro(macro_: MacroDef) -> Self {
+        Resolution { def: PerNs::macros(macro_), import: None }
+    }
+}
+
+#[derive(Debug, Clone)]
+struct ResolvePathResult {
+    resolved_def: PerNs,
+    segment_index: Option<usize>,
+    reached_fixedpoint: ReachedFixedPoint,
+}
+
+impl ResolvePathResult {
+    fn empty(reached_fixedpoint: ReachedFixedPoint) -> ResolvePathResult {
+        ResolvePathResult::with(PerNs::none(), reached_fixedpoint, None)
+    }
+
+    fn with(
+        resolved_def: PerNs,
+        reached_fixedpoint: ReachedFixedPoint,
+        segment_index: Option<usize>,
+    ) -> ResolvePathResult {
+        ResolvePathResult { resolved_def, reached_fixedpoint, segment_index }
+    }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+enum ResolveMode {
+    Import,
+    Other,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+enum ReachedFixedPoint {
+    Yes,
+    No,
+}
+
+impl CrateDefMap {
+    pub(crate) fn crate_def_map_query(
+        // Note that this doesn't have `+ AstDatabase`!
+        // This gurantess that `CrateDefMap` is stable across reparses.
+        db: &impl DefDatabase,
+        krate: Crate,
+    ) -> Arc<CrateDefMap> {
+        let _p = profile("crate_def_map_query");
+        let def_map = {
+            let edition = krate.edition(db);
+            let mut modules: Arena<CrateModuleId, ModuleData> = Arena::default();
+            let root = modules.alloc(ModuleData::default());
+            CrateDefMap {
+                krate,
+                edition,
+                extern_prelude: FxHashMap::default(),
+                prelude: None,
+                root,
+                modules,
+                poison_macros: FxHashSet::default(),
+                diagnostics: Vec::new(),
+            }
+        };
+        let def_map = collector::collect_defs(db, def_map);
+        Arc::new(def_map)
+    }
+
+    pub(crate) fn krate(&self) -> Crate {
+        self.krate
+    }
+
+    pub(crate) fn root(&self) -> CrateModuleId {
+        self.root
+    }
+
+    pub(crate) fn prelude(&self) -> Option<Module> {
+        self.prelude
+    }
+
+    pub(crate) fn extern_prelude(&self) -> &FxHashMap<Name, ModuleDef> {
+        &self.extern_prelude
+    }
+
+    pub(crate) fn add_diagnostics(
+        &self,
+        db: &(impl DefDatabase + AstDatabase),
+        module: CrateModuleId,
+        sink: &mut DiagnosticSink,
+    ) {
+        self.diagnostics.iter().for_each(|it| it.add_to(db, module, sink))
+    }
+
+    pub(crate) fn find_module_by_source(
+        &self,
+        file_id: HirFileId,
+        decl_id: Option<AstId<ast::Module>>,
+    ) -> Option<CrateModuleId> {
+        let (module_id, _module_data) = self.modules.iter().find(|(_module_id, module_data)| {
+            if decl_id.is_some() {
+                module_data.declaration == decl_id
+            } else {
+                module_data.definition.map(|it| it.into()) == Some(file_id)
+            }
+        })?;
+        Some(module_id)
+    }
+
+    pub(crate) fn resolve_path(
+        &self,
+        db: &impl DefDatabase,
+        original_module: CrateModuleId,
+        path: &Path,
+    ) -> (PerNs, Option<usize>) {
+        let res = self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path);
+        (res.resolved_def, res.segment_index)
+    }
+
+    // Returns Yes if we are sure that additions to `ItemMap` wouldn't change
+    // the result.
+    fn resolve_path_fp_with_macro(
+        &self,
+        db: &impl DefDatabase,
+        mode: ResolveMode,
+        original_module: CrateModuleId,
+        path: &Path,
+    ) -> ResolvePathResult {
+        let mut segments = path.segments.iter().enumerate();
+        let mut curr_per_ns: PerNs = match path.kind {
+            PathKind::DollarCrate(crate_id) => {
+                let krate = Crate { crate_id };
+                if krate == self.krate {
+                    tested_by!(macro_dollar_crate_self);
+                    PerNs::types(Module::new(self.krate, self.root).into())
+                } else {
+                    match krate.root_module(db) {
+                        Some(module) => {
+                            tested_by!(macro_dollar_crate_other);
+                            PerNs::types(module.into())
+                        }
+                        None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
+                    }
+                }
+            }
+            PathKind::Crate => PerNs::types(Module::new(self.krate, self.root).into()),
+            PathKind::Self_ => PerNs::types(Module::new(self.krate, original_module).into()),
+            // plain import or absolute path in 2015: crate-relative with
+            // fallback to extern prelude (with the simplification in
+            // rust-lang/rust#57745)
+            // FIXME there must be a nicer way to write this condition
+            PathKind::Plain | PathKind::Abs
+                if self.edition == Edition::Edition2015
+                    && (path.kind == PathKind::Abs || mode == ResolveMode::Import) =>
+            {
+                let segment = match segments.next() {
+                    Some((_, segment)) => segment,
+                    None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
+                };
+                log::debug!("resolving {:?} in crate root (+ extern prelude)", segment);
+                self.resolve_name_in_crate_root_or_extern_prelude(&segment.name)
+            }
+            PathKind::Plain => {
+                let segment = match segments.next() {
+                    Some((_, segment)) => segment,
+                    None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
+                };
+                log::debug!("resolving {:?} in module", segment);
+                self.resolve_name_in_module(db, original_module, &segment.name)
+            }
+            PathKind::Super => {
+                if let Some(p) = self.modules[original_module].parent {
+                    PerNs::types(Module::new(self.krate, p).into())
+                } else {
+                    log::debug!("super path in root module");
+                    return ResolvePathResult::empty(ReachedFixedPoint::Yes);
+                }
+            }
+            PathKind::Abs => {
+                // 2018-style absolute path -- only extern prelude
+                let segment = match segments.next() {
+                    Some((_, segment)) => segment,
+                    None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
+                };
+                if let Some(def) = self.extern_prelude.get(&segment.name) {
+                    log::debug!("absolute path {:?} resolved to crate {:?}", path, def);
+                    PerNs::types(*def)
+                } else {
+                    return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude
+                }
+            }
+            PathKind::Type(_) => {
+                // This is handled in `infer::infer_path_expr`
+                // The result returned here does not matter
+                return ResolvePathResult::empty(ReachedFixedPoint::Yes);
+            }
+        };
+
+        for (i, segment) in segments {
+            let curr = match curr_per_ns.take_types() {
+                Some(r) => r,
+                None => {
+                    // we still have path segments left, but the path so far
+                    // didn't resolve in the types namespace => no resolution
+                    // (don't break here because `curr_per_ns` might contain
+                    // something in the value namespace, and it would be wrong
+                    // to return that)
+                    return ResolvePathResult::empty(ReachedFixedPoint::No);
+                }
+            };
+            // resolve segment in curr
+
+            curr_per_ns = match curr {
+                ModuleDef::Module(module) => {
+                    if module.krate() != self.krate {
+                        let path =
+                            Path { segments: path.segments[i..].to_vec(), kind: PathKind::Self_ };
+                        log::debug!("resolving {:?} in other crate", path);
+                        let defp_map = db.crate_def_map(module.krate());
+                        let (def, s) = defp_map.resolve_path(db, module.id.module_id, &path);
+                        return ResolvePathResult::with(
+                            def,
+                            ReachedFixedPoint::Yes,
+                            s.map(|s| s + i),
+                        );
+                    }
+
+                    // Since it is a qualified path here, it should not contains legacy macros
+                    match self[module.id.module_id].scope.get(&segment.name) {
+                        Some(res) => res.def,
+                        _ => {
+                            log::debug!("path segment {:?} not found", segment.name);
+                            return ResolvePathResult::empty(ReachedFixedPoint::No);
+                        }
+                    }
+                }
+                ModuleDef::Adt(Adt::Enum(e)) => {
+                    // enum variant
+                    tested_by!(can_import_enum_variant);
+                    match e.variant(db, &segment.name) {
+                        Some(variant) => PerNs::both(variant.into(), variant.into()),
+                        None => {
+                            return ResolvePathResult::with(
+                                PerNs::types(e.into()),
+                                ReachedFixedPoint::Yes,
+                                Some(i),
+                            );
+                        }
+                    }
+                }
+                s => {
+                    // could be an inherent method call in UFCS form
+                    // (`Struct::method`), or some other kind of associated item
+                    log::debug!(
+                        "path segment {:?} resolved to non-module {:?}, but is not last",
+                        segment.name,
+                        curr,
+                    );
+
+                    return ResolvePathResult::with(
+                        PerNs::types(s),
+                        ReachedFixedPoint::Yes,
+                        Some(i),
+                    );
+                }
+            };
+        }
+        ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None)
+    }
+
+    fn resolve_name_in_crate_root_or_extern_prelude(&self, name: &Name) -> PerNs {
+        let from_crate_root =
+            self[self.root].scope.get(name).map_or_else(PerNs::none, |res| res.def);
+        let from_extern_prelude = self.resolve_name_in_extern_prelude(name);
+
+        from_crate_root.or(from_extern_prelude)
+    }
+
+    pub(crate) fn resolve_name_in_module(
+        &self,
+        db: &impl DefDatabase,
+        module: CrateModuleId,
+        name: &Name,
+    ) -> PerNs {
+        // Resolve in:
+        //  - legacy scope of macro
+        //  - current module / scope
+        //  - extern prelude
+        //  - std prelude
+        let from_legacy_macro =
+            self[module].scope.get_legacy_macro(name).map_or_else(PerNs::none, PerNs::macros);
+        let from_scope = self[module].scope.get(name).map_or_else(PerNs::none, |res| res.def);
+        let from_extern_prelude =
+            self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it));
+        let from_prelude = self.resolve_in_prelude(db, name);
+
+        from_legacy_macro.or(from_scope).or(from_extern_prelude).or(from_prelude)
+    }
+
+    fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs {
+        self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it))
+    }
+
+    fn resolve_in_prelude(&self, db: &impl DefDatabase, name: &Name) -> PerNs {
+        if let Some(prelude) = self.prelude {
+            let keep;
+            let def_map = if prelude.krate() == self.krate {
+                self
+            } else {
+                // Extend lifetime
+                keep = db.crate_def_map(prelude.krate());
+                &keep
+            };
+            def_map[prelude.id.module_id].scope.get(name).map_or_else(PerNs::none, |res| res.def)
+        } else {
+            PerNs::none()
+        }
+    }
+}
+
+mod diagnostics {
+    use hir_expand::diagnostics::DiagnosticSink;
+    use ra_syntax::{ast, AstPtr};
+    use relative_path::RelativePathBuf;
+
+    use crate::{
+        db::{AstDatabase, DefDatabase},
+        diagnostics::UnresolvedModule,
+        nameres::CrateModuleId,
+        AstId,
+    };
+
+    #[derive(Debug, PartialEq, Eq)]
+    pub(super) enum DefDiagnostic {
+        UnresolvedModule {
+            module: CrateModuleId,
+            declaration: AstId<ast::Module>,
+            candidate: RelativePathBuf,
+        },
+    }
+
+    impl DefDiagnostic {
+        pub(super) fn add_to(
+            &self,
+            db: &(impl DefDatabase + AstDatabase),
+            target_module: CrateModuleId,
+            sink: &mut DiagnosticSink,
+        ) {
+            match self {
+                DefDiagnostic::UnresolvedModule { module, declaration, candidate } => {
+                    if *module != target_module {
+                        return;
+                    }
+                    let decl = declaration.to_node(db);
+                    sink.push(UnresolvedModule {
+                        file: declaration.file_id(),
+                        decl: AstPtr::new(&decl),
+                        candidate: candidate.clone(),
+                    })
+                }
+            }
+        }
+    }
+}
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs
similarity index 86%
rename from crates/ra_hir_def/src/nameres/collector.rs
rename to crates/ra_hir/src/nameres/collector.rs
index 3b61d9895b..ee0a4c99fe 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir/src/nameres/collector.rs
@@ -1,49 +1,45 @@
 //! FIXME: write short doc here
 
-use hir_expand::{
-    name::{self, AsName, Name},
-    HirFileId, MacroCallId, MacroCallLoc, MacroDefId, MacroFileKind,
+use hir_def::{
+    attr::Attr,
+    nameres::{mod_resolution::ModDir, raw},
 };
+use hir_expand::name;
 use ra_cfg::CfgOptions;
-use ra_db::{CrateId, FileId};
+use ra_db::FileId;
 use ra_syntax::{ast, SmolStr};
 use rustc_hash::FxHashMap;
 use test_utils::tested_by;
 
 use crate::{
-    attr::Attr,
-    db::DefDatabase2,
+    db::DefDatabase,
+    ids::{AstItemDef, LocationCtx, MacroCallId, MacroCallLoc, MacroDefId, MacroFileKind},
     nameres::{
-        diagnostics::DefDiagnostic, mod_resolution::ModDir, per_ns::PerNs, raw, CrateDefMap,
-        ModuleData, ReachedFixedPoint, Resolution, ResolveMode,
+        diagnostics::DefDiagnostic, Crate, CrateDefMap, CrateModuleId, ModuleData, ModuleDef,
+        PerNs, ReachedFixedPoint, Resolution, ResolveMode,
     },
-    path::{Path, PathKind},
-    AdtId, AstId, AstItemDef, ConstId, CrateModuleId, EnumId, EnumVariantId, FunctionId,
-    LocationCtx, ModuleDefId, ModuleId, StaticId, StructId, TraitId, TypeAliasId, UnionId,
+    Adt, AstId, Const, Enum, Function, HirFileId, MacroDef, Module, Name, Path, PathKind, Static,
+    Struct, Trait, TypeAlias, Union,
 };
 
-pub(super) fn collect_defs(db: &impl DefDatabase2, mut def_map: CrateDefMap) -> CrateDefMap {
-    let crate_graph = db.crate_graph();
-
+pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap {
     // populate external prelude
-    for dep in crate_graph.dependencies(def_map.krate) {
-        let dep_def_map = db.crate_def_map(dep.crate_id);
-        log::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id);
-        def_map.extern_prelude.insert(
-            dep.as_name(),
-            ModuleId { krate: dep.crate_id, module_id: dep_def_map.root }.into(),
-        );
-
+    for dep in def_map.krate.dependencies(db) {
+        log::debug!("crate dep {:?} -> {:?}", dep.name, dep.krate);
+        if let Some(module) = dep.krate.root_module(db) {
+            def_map.extern_prelude.insert(dep.name.clone(), module.into());
+        }
         // look for the prelude
         if def_map.prelude.is_none() {
-            let map = db.crate_def_map(dep.crate_id);
+            let map = db.crate_def_map(dep.krate);
             if map.prelude.is_some() {
                 def_map.prelude = map.prelude;
             }
         }
     }
 
-    let cfg_options = crate_graph.cfg_options(def_map.krate);
+    let crate_graph = db.crate_graph();
+    let cfg_options = crate_graph.cfg_options(def_map.krate().crate_id());
 
     let mut collector = DefCollector {
         db,
@@ -105,11 +101,11 @@ struct DefCollector<'a, DB> {
 
 impl<DB> DefCollector<'_, DB>
 where
-    DB: DefDatabase2,
+    DB: DefDatabase,
 {
     fn collect(&mut self) {
         let crate_graph = self.db.crate_graph();
-        let file_id = crate_graph.crate_root(self.def_map.krate);
+        let file_id = crate_graph.crate_root(self.def_map.krate.crate_id());
         let raw_items = self.db.raw_items(file_id.into());
         let module_id = self.def_map.root;
         self.def_map.modules[module_id].definition = Some(file_id);
@@ -172,7 +168,7 @@ where
         &mut self,
         module_id: CrateModuleId,
         name: Name,
-        macro_: MacroDefId,
+        macro_: MacroDef,
         export: bool,
     ) {
         // Textual scoping
@@ -193,7 +189,7 @@ where
     /// the definition of current module.
     /// And also, `macro_use` on a module will import all legacy macros visable inside to
     /// current legacy scope, with possible shadowing.
-    fn define_legacy_macro(&mut self, module_id: CrateModuleId, name: Name, macro_: MacroDefId) {
+    fn define_legacy_macro(&mut self, module_id: CrateModuleId, name: Name, macro_: MacroDef) {
         // Always shadowing
         self.def_map.modules[module_id].scope.legacy_macros.insert(name, macro_);
     }
@@ -217,9 +213,9 @@ where
                 .expect("extern crate should have been desugared to one-element path"),
         );
 
-        if let Some(ModuleDefId::ModuleId(m)) = res.take_types() {
+        if let Some(ModuleDef::Module(m)) = res.take_types() {
             tested_by!(macro_rules_from_other_crates_are_visible_with_macro_use);
-            self.import_all_macros_exported(current_module_id, m.krate);
+            self.import_all_macros_exported(current_module_id, m.krate());
         }
     }
 
@@ -228,7 +224,7 @@ where
     /// Exported macros are just all macros in the root module scope.
     /// Note that it contains not only all `#[macro_export]` macros, but also all aliases
     /// created by `use` in the root module, ignoring the visibility of `use`.
-    fn import_all_macros_exported(&mut self, current_module_id: CrateModuleId, krate: CrateId) {
+    fn import_all_macros_exported(&mut self, current_module_id: CrateModuleId, krate: Crate) {
         let def_map = self.db.crate_def_map(krate);
         for (name, def) in def_map[def_map.root].scope.macros() {
             // `macro_use` only bring things into legacy scope.
@@ -292,15 +288,15 @@ where
         if import.is_glob {
             log::debug!("glob import: {:?}", import);
             match def.take_types() {
-                Some(ModuleDefId::ModuleId(m)) => {
+                Some(ModuleDef::Module(m)) => {
                     if import.is_prelude {
                         tested_by!(std_prelude);
                         self.def_map.prelude = Some(m);
-                    } else if m.krate != self.def_map.krate {
+                    } else if m.krate() != self.def_map.krate {
                         tested_by!(glob_across_crates);
                         // glob import from other crate => we can just import everything once
-                        let item_map = self.db.crate_def_map(m.krate);
-                        let scope = &item_map[m.module_id].scope;
+                        let item_map = self.db.crate_def_map(m.krate());
+                        let scope = &item_map[m.id.module_id].scope;
 
                         // Module scoped macros is included
                         let items = scope
@@ -314,7 +310,7 @@ where
                         // glob import from same crate => we do an initial
                         // import, and then need to propagate any further
                         // additions
-                        let scope = &self.def_map[m.module_id].scope;
+                        let scope = &self.def_map[m.id.module_id].scope;
 
                         // Module scoped macros is included
                         let items = scope
@@ -326,25 +322,23 @@ where
                         self.update(module_id, Some(import_id), &items);
                         // record the glob import in case we add further items
                         self.glob_imports
-                            .entry(m.module_id)
+                            .entry(m.id.module_id)
                             .or_default()
                             .push((module_id, import_id));
                     }
                 }
-                Some(ModuleDefId::AdtId(AdtId::EnumId(e))) => {
+                Some(ModuleDef::Adt(Adt::Enum(e))) => {
                     tested_by!(glob_enum);
                     // glob import from enum => just import all the variants
-                    let enum_data = self.db.enum_data(e);
-                    let resolutions = enum_data
-                        .variants
-                        .iter()
-                        .filter_map(|(local_id, variant_data)| {
-                            let name = variant_data.name.clone()?;
-                            let variant = EnumVariantId { parent: e, local_id };
+                    let variants = e.variants(self.db);
+                    let resolutions = variants
+                        .into_iter()
+                        .filter_map(|variant| {
                             let res = Resolution {
                                 def: PerNs::both(variant.into(), variant.into()),
                                 import: Some(import_id),
                             };
+                            let name = variant.name(self.db)?;
                             Some((name, res))
                         })
                         .collect::<Vec<_>>();
@@ -457,8 +451,8 @@ where
             );
 
             if let Some(def) = resolved_res.resolved_def.get_macros() {
-                let call_id = self.db.intern_macro(MacroCallLoc { def, ast_id: *ast_id });
-                resolved.push((*module_id, call_id, def));
+                let call_id = self.db.intern_macro(MacroCallLoc { def: def.id, ast_id: *ast_id });
+                resolved.push((*module_id, call_id, def.id));
                 res = ReachedFixedPoint::No;
                 return false;
             }
@@ -523,7 +517,7 @@ struct ModCollector<'a, D> {
 
 impl<DB> ModCollector<'_, &'_ mut DefCollector<'_, DB>>
 where
-    DB: DefDatabase2,
+    DB: DefDatabase,
 {
     fn collect(&mut self, items: &[raw::RawItem]) {
         // Note: don't assert that inserted value is fresh: it's simply not true
@@ -532,9 +526,10 @@ where
 
         // Prelude module is always considered to be `#[macro_use]`.
         if let Some(prelude_module) = self.def_collector.def_map.prelude {
-            if prelude_module.krate != self.def_collector.def_map.krate {
+            if prelude_module.krate() != self.def_collector.def_map.krate {
                 tested_by!(prelude_is_macro_use);
-                self.def_collector.import_all_macros_exported(self.module_id, prelude_module.krate);
+                self.def_collector
+                    .import_all_macros_exported(self.module_id, prelude_module.krate());
             }
         }
 
@@ -640,9 +635,7 @@ where
         modules[res].scope.legacy_macros = modules[self.module_id].scope.legacy_macros.clone();
         modules[self.module_id].children.insert(name.clone(), res);
         let resolution = Resolution {
-            def: PerNs::types(
-                ModuleId { krate: self.def_collector.def_map.krate, module_id: res }.into(),
-            ),
+            def: PerNs::types(Module::new(self.def_collector.def_map.krate, res).into()),
             import: None,
         };
         self.def_collector.update(self.module_id, None, &[(name, resolution)]);
@@ -650,32 +643,30 @@ where
     }
 
     fn define_def(&mut self, def: &raw::DefData) {
-        let module =
-            ModuleId { krate: self.def_collector.def_map.krate, module_id: self.module_id };
-        let ctx = LocationCtx::new(self.def_collector.db, module, self.file_id);
+        let module = Module::new(self.def_collector.def_map.krate, self.module_id);
+        let ctx = LocationCtx::new(self.def_collector.db, module.id, self.file_id);
 
+        macro_rules! def {
+            ($kind:ident, $ast_id:ident) => {
+                $kind { id: AstItemDef::from_ast_id(ctx, $ast_id) }.into()
+            };
+        }
         let name = def.name.clone();
         let def: PerNs = match def.kind {
-            raw::DefKind::Function(ast_id) => {
-                PerNs::values(FunctionId::from_ast_id(ctx, ast_id).into())
-            }
+            raw::DefKind::Function(ast_id) => PerNs::values(def!(Function, ast_id)),
             raw::DefKind::Struct(ast_id) => {
-                let s = StructId::from_ast_id(ctx, ast_id).into();
+                let s = def!(Struct, ast_id);
                 PerNs::both(s, s)
             }
             raw::DefKind::Union(ast_id) => {
-                let s = UnionId::from_ast_id(ctx, ast_id).into();
+                let s = def!(Union, ast_id);
                 PerNs::both(s, s)
             }
-            raw::DefKind::Enum(ast_id) => PerNs::types(EnumId::from_ast_id(ctx, ast_id).into()),
-            raw::DefKind::Const(ast_id) => PerNs::values(ConstId::from_ast_id(ctx, ast_id).into()),
-            raw::DefKind::Static(ast_id) => {
-                PerNs::values(StaticId::from_ast_id(ctx, ast_id).into())
-            }
-            raw::DefKind::Trait(ast_id) => PerNs::types(TraitId::from_ast_id(ctx, ast_id).into()),
-            raw::DefKind::TypeAlias(ast_id) => {
-                PerNs::types(TypeAliasId::from_ast_id(ctx, ast_id).into())
-            }
+            raw::DefKind::Enum(ast_id) => PerNs::types(def!(Enum, ast_id)),
+            raw::DefKind::Const(ast_id) => PerNs::values(def!(Const, ast_id)),
+            raw::DefKind::Static(ast_id) => PerNs::values(def!(Static, ast_id)),
+            raw::DefKind::Trait(ast_id) => PerNs::types(def!(Trait, ast_id)),
+            raw::DefKind::TypeAlias(ast_id) => PerNs::types(def!(TypeAlias, ast_id)),
         };
         let resolution = Resolution { def, import: None };
         self.def_collector.update(self.module_id, None, &[(name, resolution)])
@@ -687,8 +678,10 @@ where
         // Case 1: macro rules, define a macro in crate-global mutable scope
         if is_macro_rules(&mac.path) {
             if let Some(name) = &mac.name {
-                let macro_id = MacroDefId { ast_id, krate: self.def_collector.def_map.krate };
-                self.def_collector.define_macro(self.module_id, name.clone(), macro_id, mac.export);
+                let macro_id =
+                    MacroDefId { ast_id, krate: self.def_collector.def_map.krate.crate_id };
+                let macro_ = MacroDef { id: macro_id };
+                self.def_collector.define_macro(self.module_id, name.clone(), macro_, mac.export);
             }
             return;
         }
@@ -698,10 +691,10 @@ where
         if let Some(macro_def) = mac.path.as_ident().and_then(|name| {
             self.def_collector.def_map[self.module_id].scope.get_legacy_macro(&name)
         }) {
-            let macro_call_id =
-                self.def_collector.db.intern_macro(MacroCallLoc { def: macro_def, ast_id });
+            let def = macro_def.id;
+            let macro_call_id = self.def_collector.db.intern_macro(MacroCallLoc { def, ast_id });
 
-            self.def_collector.collect_macro_expansion(self.module_id, macro_call_id, macro_def);
+            self.def_collector.collect_macro_expansion(self.module_id, macro_call_id, def);
             return;
         }
 
@@ -740,16 +733,15 @@ fn is_macro_rules(path: &Path) -> bool {
 
 #[cfg(test)]
 mod tests {
-    use ra_arena::Arena;
-    use ra_db::{fixture::WithFixture, SourceDatabase};
-    use rustc_hash::FxHashSet;
-
-    use crate::{db::DefDatabase2, test_db::TestDB};
+    use ra_db::SourceDatabase;
 
     use super::*;
+    use crate::{db::DefDatabase, mock::MockDatabase, Crate};
+    use ra_arena::Arena;
+    use rustc_hash::FxHashSet;
 
     fn do_collect_defs(
-        db: &impl DefDatabase2,
+        db: &impl DefDatabase,
         def_map: CrateDefMap,
         monitor: MacroStackMonitor,
     ) -> CrateDefMap {
@@ -768,11 +760,12 @@ mod tests {
     }
 
     fn do_limited_resolve(code: &str, limit: u32, poison_limit: u32) -> CrateDefMap {
-        let (db, _file_id) = TestDB::with_single_file(&code);
-        let krate = db.crate_graph().iter().next().unwrap();
+        let (db, _source_root, _) = MockDatabase::with_single_file(&code);
+        let crate_id = db.crate_graph().iter().next().unwrap();
+        let krate = Crate { crate_id };
 
         let def_map = {
-            let edition = db.crate_graph().edition(krate);
+            let edition = krate.edition(&db);
             let mut modules: Arena<CrateModuleId, ModuleData> = Arena::default();
             let root = modules.alloc(ModuleData::default());
             CrateDefMap {
diff --git a/crates/ra_hir_def/src/nameres/per_ns.rs b/crates/ra_hir/src/nameres/per_ns.rs
similarity index 75%
rename from crates/ra_hir_def/src/nameres/per_ns.rs
rename to crates/ra_hir/src/nameres/per_ns.rs
index 298b0b0c72..0da6789de6 100644
--- a/crates/ra_hir_def/src/nameres/per_ns.rs
+++ b/crates/ra_hir/src/nameres/per_ns.rs
@@ -1,8 +1,6 @@
 //! FIXME: write short doc here
 
-use hir_expand::MacroDefId;
-
-use crate::ModuleDefId;
+use crate::{MacroDef, ModuleDef};
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
 pub enum Namespace {
@@ -14,11 +12,11 @@ pub enum Namespace {
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub struct PerNs {
-    pub types: Option<ModuleDefId>,
-    pub values: Option<ModuleDefId>,
+    pub types: Option<ModuleDef>,
+    pub values: Option<ModuleDef>,
     /// Since macros has different type, many methods simply ignore it.
     /// We can only use special method like `get_macros` to access it.
-    pub macros: Option<MacroDefId>,
+    pub macros: Option<MacroDef>,
 }
 
 impl Default for PerNs {
@@ -32,19 +30,19 @@ impl PerNs {
         PerNs { types: None, values: None, macros: None }
     }
 
-    pub fn values(t: ModuleDefId) -> PerNs {
+    pub fn values(t: ModuleDef) -> PerNs {
         PerNs { types: None, values: Some(t), macros: None }
     }
 
-    pub fn types(t: ModuleDefId) -> PerNs {
+    pub fn types(t: ModuleDef) -> PerNs {
         PerNs { types: Some(t), values: None, macros: None }
     }
 
-    pub fn both(types: ModuleDefId, values: ModuleDefId) -> PerNs {
+    pub fn both(types: ModuleDef, values: ModuleDef) -> PerNs {
         PerNs { types: Some(types), values: Some(values), macros: None }
     }
 
-    pub fn macros(macro_: MacroDefId) -> PerNs {
+    pub fn macros(macro_: MacroDef) -> PerNs {
         PerNs { types: None, values: None, macros: Some(macro_) }
     }
 
@@ -56,15 +54,15 @@ impl PerNs {
         self.types.is_some() && self.values.is_some() && self.macros.is_some()
     }
 
-    pub fn take_types(self) -> Option<ModuleDefId> {
+    pub fn take_types(self) -> Option<ModuleDef> {
         self.types
     }
 
-    pub fn take_values(self) -> Option<ModuleDefId> {
+    pub fn take_values(self) -> Option<ModuleDef> {
         self.values
     }
 
-    pub fn get_macros(&self) -> Option<MacroDefId> {
+    pub fn get_macros(&self) -> Option<MacroDef> {
         self.macros
     }
 
diff --git a/crates/ra_hir_def/src/nameres/tests/primitives.rs b/crates/ra_hir/src/nameres/tests/primitives.rs
similarity index 100%
rename from crates/ra_hir_def/src/nameres/tests/primitives.rs
rename to crates/ra_hir/src/nameres/tests/primitives.rs
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs
index b932b0c8cd..75b24d386f 100644
--- a/crates/ra_hir/src/resolve.rs
+++ b/crates/ra_hir/src/resolve.rs
@@ -3,9 +3,8 @@ use std::sync::Arc;
 
 use hir_def::{
     builtin_type::BuiltinType,
-    nameres::CrateDefMap,
     path::{Path, PathKind},
-    AdtId, CrateModuleId, ModuleDefId,
+    CrateModuleId,
 };
 use hir_expand::name::{self, Name};
 use rustc_hash::FxHashSet;
@@ -19,8 +18,8 @@ use crate::{
     },
     generics::GenericParams,
     impl_block::ImplBlock,
-    Adt, Const, Enum, EnumVariant, Function, MacroDef, ModuleDef, PerNs, Static, Struct, Trait,
-    TypeAlias,
+    nameres::{CrateDefMap, PerNs},
+    Adt, Const, Enum, EnumVariant, Function, MacroDef, ModuleDef, Static, Struct, Trait, TypeAlias,
 };
 
 #[derive(Debug, Clone, Default)]
@@ -91,7 +90,7 @@ impl Resolver {
     pub(crate) fn resolve_known_trait(&self, db: &impl HirDatabase, path: &Path) -> Option<Trait> {
         let res = self.resolve_module_path(db, path).take_types()?;
         match res {
-            ModuleDefId::TraitId(it) => Some(it.into()),
+            ModuleDef::Trait(it) => Some(it),
             _ => None,
         }
     }
@@ -104,7 +103,7 @@ impl Resolver {
     ) -> Option<Struct> {
         let res = self.resolve_module_path(db, path).take_types()?;
         match res {
-            ModuleDefId::AdtId(AdtId::StructId(it)) => Some(it.into()),
+            ModuleDef::Adt(Adt::Struct(it)) => Some(it),
             _ => None,
         }
     }
@@ -113,7 +112,7 @@ impl Resolver {
     pub(crate) fn resolve_known_enum(&self, db: &impl HirDatabase, path: &Path) -> Option<Enum> {
         let res = self.resolve_module_path(db, path).take_types()?;
         match res {
-            ModuleDefId::AdtId(AdtId::EnumId(it)) => Some(it.into()),
+            ModuleDef::Adt(Adt::Enum(it)) => Some(it),
             _ => None,
         }
     }
@@ -167,18 +166,18 @@ impl Resolver {
                 Scope::ModuleScope(m) => {
                     let (module_def, idx) = m.crate_def_map.resolve_path(db, m.module_id, path);
                     let res = match module_def.take_types()? {
-                        ModuleDefId::AdtId(it) => TypeNs::Adt(it.into()),
-                        ModuleDefId::EnumVariantId(it) => TypeNs::EnumVariant(it.into()),
+                        ModuleDef::Adt(it) => TypeNs::Adt(it),
+                        ModuleDef::EnumVariant(it) => TypeNs::EnumVariant(it),
 
-                        ModuleDefId::TypeAliasId(it) => TypeNs::TypeAlias(it.into()),
-                        ModuleDefId::BuiltinType(it) => TypeNs::BuiltinType(it),
+                        ModuleDef::TypeAlias(it) => TypeNs::TypeAlias(it),
+                        ModuleDef::BuiltinType(it) => TypeNs::BuiltinType(it),
 
-                        ModuleDefId::TraitId(it) => TypeNs::Trait(it.into()),
+                        ModuleDef::Trait(it) => TypeNs::Trait(it),
 
-                        ModuleDefId::FunctionId(_)
-                        | ModuleDefId::ConstId(_)
-                        | ModuleDefId::StaticId(_)
-                        | ModuleDefId::ModuleId(_) => return None,
+                        ModuleDef::Function(_)
+                        | ModuleDef::Const(_)
+                        | ModuleDef::Static(_)
+                        | ModuleDef::Module(_) => return None,
                     };
                     return Some((res, idx));
                 }
@@ -262,35 +261,33 @@ impl Resolver {
                     return match idx {
                         None => {
                             let value = match module_def.take_values()? {
-                                ModuleDefId::FunctionId(it) => ValueNs::Function(it.into()),
-                                ModuleDefId::AdtId(AdtId::StructId(it)) => {
-                                    ValueNs::Struct(it.into())
-                                }
-                                ModuleDefId::EnumVariantId(it) => ValueNs::EnumVariant(it.into()),
-                                ModuleDefId::ConstId(it) => ValueNs::Const(it.into()),
-                                ModuleDefId::StaticId(it) => ValueNs::Static(it.into()),
-
-                                ModuleDefId::AdtId(AdtId::EnumId(_))
-                                | ModuleDefId::AdtId(AdtId::UnionId(_))
-                                | ModuleDefId::TraitId(_)
-                                | ModuleDefId::TypeAliasId(_)
-                                | ModuleDefId::BuiltinType(_)
-                                | ModuleDefId::ModuleId(_) => return None,
+                                ModuleDef::Function(it) => ValueNs::Function(it),
+                                ModuleDef::Adt(Adt::Struct(it)) => ValueNs::Struct(it),
+                                ModuleDef::EnumVariant(it) => ValueNs::EnumVariant(it),
+                                ModuleDef::Const(it) => ValueNs::Const(it),
+                                ModuleDef::Static(it) => ValueNs::Static(it),
+
+                                ModuleDef::Adt(Adt::Enum(_))
+                                | ModuleDef::Adt(Adt::Union(_))
+                                | ModuleDef::Trait(_)
+                                | ModuleDef::TypeAlias(_)
+                                | ModuleDef::BuiltinType(_)
+                                | ModuleDef::Module(_) => return None,
                             };
                             Some(ResolveValueResult::ValueNs(value))
                         }
                         Some(idx) => {
                             let ty = match module_def.take_types()? {
-                                ModuleDefId::AdtId(it) => TypeNs::Adt(it.into()),
-                                ModuleDefId::TraitId(it) => TypeNs::Trait(it.into()),
-                                ModuleDefId::TypeAliasId(it) => TypeNs::TypeAlias(it.into()),
-                                ModuleDefId::BuiltinType(it) => TypeNs::BuiltinType(it),
-
-                                ModuleDefId::ModuleId(_)
-                                | ModuleDefId::FunctionId(_)
-                                | ModuleDefId::EnumVariantId(_)
-                                | ModuleDefId::ConstId(_)
-                                | ModuleDefId::StaticId(_) => return None,
+                                ModuleDef::Adt(it) => TypeNs::Adt(it),
+                                ModuleDef::Trait(it) => TypeNs::Trait(it),
+                                ModuleDef::TypeAlias(it) => TypeNs::TypeAlias(it),
+                                ModuleDef::BuiltinType(it) => TypeNs::BuiltinType(it),
+
+                                ModuleDef::Module(_)
+                                | ModuleDef::Function(_)
+                                | ModuleDef::EnumVariant(_)
+                                | ModuleDef::Const(_)
+                                | ModuleDef::Static(_) => return None,
                             };
                             Some(ResolveValueResult::Partial(ty, idx))
                         }
@@ -318,7 +315,7 @@ impl Resolver {
         path: &Path,
     ) -> Option<MacroDef> {
         let (item_map, module) = self.module()?;
-        item_map.resolve_path(db, module, path).0.get_macros().map(MacroDef::from)
+        item_map.resolve_path(db, module, path).0.get_macros()
     }
 
     pub(crate) fn process_all_names(
@@ -336,11 +333,10 @@ impl Resolver {
         for scope in &self.scopes {
             if let Scope::ModuleScope(m) = scope {
                 if let Some(prelude) = m.crate_def_map.prelude() {
-                    let prelude_def_map = db.crate_def_map(prelude.krate);
-                    traits
-                        .extend(prelude_def_map[prelude.module_id].scope.traits().map(Trait::from));
+                    let prelude_def_map = db.crate_def_map(prelude.krate());
+                    traits.extend(prelude_def_map[prelude.id.module_id].scope.traits());
                 }
-                traits.extend(m.crate_def_map[m.module_id].scope.traits().map(Trait::from));
+                traits.extend(m.crate_def_map[m.module_id].scope.traits());
             }
         }
         traits
@@ -355,7 +351,7 @@ impl Resolver {
     }
 
     pub(crate) fn krate(&self) -> Option<Crate> {
-        self.module().map(|t| Crate { crate_id: t.0.krate() })
+        self.module().map(|t| t.0.krate())
     }
 
     pub(crate) fn where_predicates_in_scope<'a>(
@@ -424,10 +420,8 @@ impl From<PerNs> for ScopeDef {
     fn from(def: PerNs) -> Self {
         def.take_types()
             .or_else(|| def.take_values())
-            .map(|module_def_id| ScopeDef::ModuleDef(module_def_id.into()))
-            .or_else(|| {
-                def.get_macros().map(|macro_def_id| ScopeDef::MacroDef(macro_def_id.into()))
-            })
+            .map(ScopeDef::ModuleDef)
+            .or_else(|| def.get_macros().map(ScopeDef::MacroDef))
             .unwrap_or(ScopeDef::Unknown)
     }
 }
@@ -447,16 +441,18 @@ impl Scope {
                     f(name.clone(), res.def.into());
                 });
                 m.crate_def_map[m.module_id].scope.legacy_macros().for_each(|(name, macro_)| {
-                    f(name.clone(), ScopeDef::MacroDef(macro_.into()));
+                    f(name.clone(), ScopeDef::MacroDef(macro_));
                 });
-                m.crate_def_map.extern_prelude().iter().for_each(|(name, &def)| {
-                    f(name.clone(), ScopeDef::ModuleDef(def.into()));
+                m.crate_def_map.extern_prelude().iter().for_each(|(name, def)| {
+                    f(name.clone(), ScopeDef::ModuleDef(*def));
                 });
                 if let Some(prelude) = m.crate_def_map.prelude() {
-                    let prelude_def_map = db.crate_def_map(prelude.krate);
-                    prelude_def_map[prelude.module_id].scope.entries().for_each(|(name, res)| {
-                        f(name.clone(), res.def.into());
-                    });
+                    let prelude_def_map = db.crate_def_map(prelude.krate());
+                    prelude_def_map[prelude.id.module_id].scope.entries().for_each(
+                        |(name, res)| {
+                            f(name.clone(), res.def.into());
+                        },
+                    );
                 }
             }
             Scope::GenericParams(gp) => {
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 66cb4b357f..a4ca59bba1 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -253,11 +253,8 @@ impl SourceAnalyzer {
             Some(res)
         });
 
-        let items = self
-            .resolver
-            .resolve_module_path(db, &path)
-            .take_types()
-            .map(|it| PathResolution::Def(it.into()));
+        let items =
+            self.resolver.resolve_module_path(db, &path).take_types().map(PathResolution::Def);
         types.or(values).or(items).or_else(|| {
             self.resolver.resolve_path_as_macro(db, &path).map(|def| PathResolution::Macro(def))
         })
diff --git a/crates/ra_hir/src/ty/infer/expr.rs b/crates/ra_hir/src/ty/infer/expr.rs
index a09ef5c5d3..fed52df39c 100644
--- a/crates/ra_hir/src/ty/infer/expr.rs
+++ b/crates/ra_hir/src/ty/infer/expr.rs
@@ -11,11 +11,12 @@ use crate::{
     db::HirDatabase,
     expr::{self, Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp},
     generics::{GenericParams, HasGenericParams},
+    nameres::Namespace,
     ty::{
         autoderef, method_resolution, op, primitive, CallableDef, InferTy, Mutability, Obligation,
         ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk,
     },
-    Adt, Name, Namespace,
+    Adt, Name,
 };
 
 impl<'a, D: HirDatabase> InferenceContext<'a, D> {
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index e29ab8492a..8e28343071 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -23,14 +23,15 @@ use crate::{
     db::HirDatabase,
     generics::HasGenericParams,
     generics::{GenericDef, WherePredicate},
+    nameres::Namespace,
     resolve::{Resolver, TypeNs},
     ty::{
         primitive::{FloatTy, IntTy},
         Adt,
     },
     util::make_mut_slice,
-    Const, Enum, EnumVariant, Function, ModuleDef, Namespace, Path, Static, Struct, StructField,
-    Trait, TypeAlias, Union,
+    Const, Enum, EnumVariant, Function, ModuleDef, Path, Static, Struct, StructField, Trait,
+    TypeAlias, Union,
 };
 
 impl Ty {
diff --git a/crates/ra_hir_def/Cargo.toml b/crates/ra_hir_def/Cargo.toml
index 21262be795..746c907e80 100644
--- a/crates/ra_hir_def/Cargo.toml
+++ b/crates/ra_hir_def/Cargo.toml
@@ -7,6 +7,7 @@ authors = ["rust-analyzer developers"]
 [dependencies]
 log = "0.4.5"
 once_cell = "1.0.1"
+relative-path = "1.0.0"
 rustc-hash = "1.0"
 
 ra_arena = { path = "../ra_arena" }
@@ -18,6 +19,3 @@ test_utils = { path = "../test_utils" }
 mbe = { path = "../ra_mbe", package = "ra_mbe" }
 ra_cfg = { path = "../ra_cfg" }
 tt = { path = "../ra_tt", package = "ra_tt" }
-
-[dev-dependencies]
-insta = "0.12.0"
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs
index 8f41e55d26..22bd469f0a 100644
--- a/crates/ra_hir_def/src/adt.rs
+++ b/crates/ra_hir_def/src/adt.rs
@@ -8,7 +8,7 @@ use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner};
 
 use crate::{
     db::DefDatabase2, type_ref::TypeRef, AstItemDef, EnumId, LocalEnumVariantId,
-    LocalStructFieldId, StructId, UnionId,
+    LocalStructFieldId, StructId,
 };
 
 /// Note that we use `StructData` for unions as well!
@@ -56,13 +56,6 @@ impl StructData {
         let variant_data = Arc::new(variant_data);
         Arc::new(StructData { name, variant_data })
     }
-    pub(crate) fn union_data_query(db: &impl DefDatabase2, struct_: UnionId) -> Arc<StructData> {
-        let src = struct_.source(db);
-        let name = src.ast.name().map(|n| n.as_name());
-        let variant_data = VariantData::new(src.ast.kind());
-        let variant_data = Arc::new(variant_data);
-        Arc::new(StructData { name, variant_data })
-    }
 }
 
 impl EnumData {
@@ -81,11 +74,6 @@ impl EnumData {
             .collect();
         Arc::new(EnumData { name, variants })
     }
-
-    pub(crate) fn variant(&self, name: &Name) -> Option<LocalEnumVariantId> {
-        let (id, _) = self.variants.iter().find(|(_id, data)| data.name.as_ref() == Some(name))?;
-        Some(id)
-    }
 }
 
 impl VariantData {
diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs
index a42348101b..f6027013f2 100644
--- a/crates/ra_hir_def/src/db.rs
+++ b/crates/ra_hir_def/src/db.rs
@@ -2,16 +2,13 @@
 use std::sync::Arc;
 
 use hir_expand::{db::AstDatabase, HirFileId};
-use ra_db::{salsa, CrateId, SourceDatabase};
+use ra_db::{salsa, SourceDatabase};
 use ra_syntax::ast;
 
 use crate::{
     adt::{EnumData, StructData},
-    nameres::{
-        raw::{ImportSourceMap, RawItems},
-        CrateDefMap,
-    },
-    EnumId, StructId, UnionId,
+    nameres::raw::{ImportSourceMap, RawItems},
+    EnumId, StructId,
 };
 
 #[salsa::query_group(InternDatabaseStorage)]
@@ -45,15 +42,9 @@ pub trait DefDatabase2: InternDatabase + AstDatabase {
     #[salsa::invoke(RawItems::raw_items_query)]
     fn raw_items(&self, file_id: HirFileId) -> Arc<RawItems>;
 
-    #[salsa::invoke(CrateDefMap::crate_def_map_query)]
-    fn crate_def_map(&self, krate: CrateId) -> Arc<CrateDefMap>;
-
     #[salsa::invoke(StructData::struct_data_query)]
     fn struct_data(&self, s: StructId) -> Arc<StructData>;
 
-    #[salsa::invoke(StructData::union_data_query)]
-    fn union_data(&self, s: UnionId) -> Arc<StructData>;
-
     #[salsa::invoke(EnumData::enum_data_query)]
     fn enum_data(&self, e: EnumId) -> Arc<EnumData>;
 }
diff --git a/crates/ra_hir_def/src/diagnostics.rs b/crates/ra_hir_def/src/diagnostics.rs
deleted file mode 100644
index 9843009a5d..0000000000
--- a/crates/ra_hir_def/src/diagnostics.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-//! Diagnostics produced by `hir_def`.
-
-use std::any::Any;
-
-use hir_expand::diagnostics::Diagnostic;
-use ra_db::RelativePathBuf;
-use ra_syntax::{ast, AstPtr, SyntaxNodePtr};
-
-use hir_expand::{HirFileId, Source};
-
-#[derive(Debug)]
-pub struct UnresolvedModule {
-    pub file: HirFileId,
-    pub decl: AstPtr<ast::Module>,
-    pub candidate: RelativePathBuf,
-}
-
-impl Diagnostic for UnresolvedModule {
-    fn message(&self) -> String {
-        "unresolved module".to_string()
-    }
-    fn source(&self) -> Source<SyntaxNodePtr> {
-        Source { file_id: self.file, ast: self.decl.into() }
-    }
-    fn as_any(&self) -> &(dyn Any + Send + 'static) {
-        self
-    }
-}
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs
index 63ed2a0983..6d66f481d3 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -13,12 +13,6 @@ pub mod path;
 pub mod type_ref;
 pub mod builtin_type;
 pub mod adt;
-pub mod diagnostics;
-
-#[cfg(test)]
-mod test_db;
-#[cfg(test)]
-mod marks;
 
 // FIXME: this should be private
 pub mod nameres;
@@ -243,8 +237,8 @@ impl AstItemDef<ast::EnumDef> for EnumId {
 // FIXME: rename to `VariantId`, only enums can ave variants
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 pub struct EnumVariantId {
-    pub parent: EnumId,
-    pub local_id: LocalEnumVariantId,
+    parent: EnumId,
+    local_id: LocalEnumVariantId,
 }
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
diff --git a/crates/ra_hir_def/src/marks.rs b/crates/ra_hir_def/src/marks.rs
deleted file mode 100644
index 0b99eac717..0000000000
--- a/crates/ra_hir_def/src/marks.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-//! See test_utils/src/marks.rs
-
-test_utils::marks!(
-    bogus_paths
-    name_res_works_for_broken_modules
-    can_import_enum_variant
-    glob_enum
-    glob_across_crates
-    std_prelude
-    macro_rules_from_other_crates_are_visible_with_macro_use
-    prelude_is_macro_use
-    macro_dollar_crate_self
-    macro_dollar_crate_other
-);
diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs
index 433bdde48f..11ba8a7770 100644
--- a/crates/ra_hir_def/src/nameres.rs
+++ b/crates/ra_hir_def/src/nameres.rs
@@ -1,543 +1,5 @@
-//! This module implements import-resolution/macro expansion algorithm.
-//!
-//! The result of this module is `CrateDefMap`: a data structure which contains:
-//!
-//!   * a tree of modules for the crate
-//!   * for each module, a set of items visible in the module (directly declared
-//!     or imported)
-//!
-//! Note that `CrateDefMap` contains fully macro expanded code.
-//!
-//! Computing `CrateDefMap` can be partitioned into several logically
-//! independent "phases". The phases are mutually recursive though, there's no
-//! strict ordering.
-//!
-//! ## Collecting RawItems
-//!
-//!  This happens in the `raw` module, which parses a single source file into a
-//!  set of top-level items. Nested imports are desugared to flat imports in
-//!  this phase. Macro calls are represented as a triple of (Path, Option<Name>,
-//!  TokenTree).
-//!
-//! ## Collecting Modules
-//!
-//! This happens in the `collector` module. In this phase, we recursively walk
-//! tree of modules, collect raw items from submodules, populate module scopes
-//! with defined items (so, we assign item ids in this phase) and record the set
-//! of unresolved imports and macros.
-//!
-//! While we walk tree of modules, we also record macro_rules definitions and
-//! expand calls to macro_rules defined macros.
-//!
-//! ## Resolving Imports
-//!
-//! We maintain a list of currently unresolved imports. On every iteration, we
-//! try to resolve some imports from this list. If the import is resolved, we
-//! record it, by adding an item to current module scope and, if necessary, by
-//! recursively populating glob imports.
-//!
-//! ## Resolving Macros
-//!
-//! macro_rules from the same crate use a global mutable namespace. We expand
-//! them immediately, when we collect modules.
-//!
-//! Macros from other crates (including proc-macros) can be used with
-//! `foo::bar!` syntax. We handle them similarly to imports. There's a list of
-//! unexpanded macros. On every iteration, we try to resolve each macro call
-//! path and, upon success, we run macro expansion and "collect module" phase
-//! on the result
+//! FIXME: write short doc here
 
 // FIXME: review privacy of submodules
 pub mod raw;
-pub mod per_ns;
-pub mod collector;
 pub mod mod_resolution;
-
-#[cfg(test)]
-mod tests;
-
-use std::sync::Arc;
-
-use hir_expand::{diagnostics::DiagnosticSink, name::Name, MacroDefId};
-use once_cell::sync::Lazy;
-use ra_arena::Arena;
-use ra_db::{CrateId, Edition, FileId};
-use ra_prof::profile;
-use ra_syntax::ast;
-use rustc_hash::{FxHashMap, FxHashSet};
-use test_utils::tested_by;
-
-use crate::{
-    builtin_type::BuiltinType,
-    db::DefDatabase2,
-    nameres::{diagnostics::DefDiagnostic, per_ns::PerNs, raw::ImportId},
-    path::{Path, PathKind},
-    AdtId, AstId, CrateModuleId, EnumVariantId, ModuleDefId, ModuleId, TraitId,
-};
-
-/// Contains all top-level defs from a macro-expanded crate
-#[derive(Debug, PartialEq, Eq)]
-pub struct CrateDefMap {
-    krate: CrateId,
-    edition: Edition,
-    /// The prelude module for this crate. This either comes from an import
-    /// marked with the `prelude_import` attribute, or (in the normal case) from
-    /// a dependency (`std` or `core`).
-    prelude: Option<ModuleId>,
-    extern_prelude: FxHashMap<Name, ModuleDefId>,
-    root: CrateModuleId,
-    pub modules: Arena<CrateModuleId, ModuleData>,
-
-    /// Some macros are not well-behavior, which leads to infinite loop
-    /// e.g. macro_rules! foo { ($ty:ty) => { foo!($ty); } }
-    /// We mark it down and skip it in collector
-    ///
-    /// FIXME:
-    /// Right now it only handle a poison macro in a single crate,
-    /// such that if other crate try to call that macro,
-    /// the whole process will do again until it became poisoned in that crate.
-    /// We should handle this macro set globally
-    /// However, do we want to put it as a global variable?
-    poison_macros: FxHashSet<MacroDefId>,
-
-    diagnostics: Vec<DefDiagnostic>,
-}
-
-impl std::ops::Index<CrateModuleId> for CrateDefMap {
-    type Output = ModuleData;
-    fn index(&self, id: CrateModuleId) -> &ModuleData {
-        &self.modules[id]
-    }
-}
-
-#[derive(Default, Debug, PartialEq, Eq)]
-pub struct ModuleData {
-    pub parent: Option<CrateModuleId>,
-    pub children: FxHashMap<Name, CrateModuleId>,
-    pub scope: ModuleScope,
-    /// None for root
-    pub declaration: Option<AstId<ast::Module>>,
-    /// None for inline modules.
-    ///
-    /// Note that non-inline modules, by definition, live inside non-macro file.
-    pub definition: Option<FileId>,
-}
-
-#[derive(Debug, Default, PartialEq, Eq, Clone)]
-pub struct ModuleScope {
-    pub items: FxHashMap<Name, Resolution>,
-    /// Macros visable in current module in legacy textual scope
-    ///
-    /// For macros invoked by an unquatified identifier like `bar!()`, `legacy_macros` will be searched in first.
-    /// If it yields no result, then it turns to module scoped `macros`.
-    /// It macros with name quatified with a path like `crate::foo::bar!()`, `legacy_macros` will be skipped,
-    /// and only normal scoped `macros` will be searched in.
-    ///
-    /// Note that this automatically inherit macros defined textually before the definition of module itself.
-    ///
-    /// Module scoped macros will be inserted into `items` instead of here.
-    // FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will
-    // be all resolved to the last one defined if shadowing happens.
-    legacy_macros: FxHashMap<Name, MacroDefId>,
-}
-
-static BUILTIN_SCOPE: Lazy<FxHashMap<Name, Resolution>> = Lazy::new(|| {
-    BuiltinType::ALL
-        .iter()
-        .map(|(name, ty)| {
-            (name.clone(), Resolution { def: PerNs::types(ty.clone().into()), import: None })
-        })
-        .collect()
-});
-
-/// Legacy macros can only be accessed through special methods like `get_legacy_macros`.
-/// Other methods will only resolve values, types and module scoped macros only.
-impl ModuleScope {
-    pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a Name, &'a Resolution)> + 'a {
-        //FIXME: shadowing
-        self.items.iter().chain(BUILTIN_SCOPE.iter())
-    }
-
-    /// Iterate over all module scoped macros
-    pub fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a {
-        self.items
-            .iter()
-            .filter_map(|(name, res)| res.def.get_macros().map(|macro_| (name, macro_)))
-    }
-
-    /// Iterate over all legacy textual scoped macros visable at the end of the module
-    pub fn legacy_macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a {
-        self.legacy_macros.iter().map(|(name, def)| (name, *def))
-    }
-
-    /// Get a name from current module scope, legacy macros are not included
-    pub fn get(&self, name: &Name) -> Option<&Resolution> {
-        self.items.get(name).or_else(|| BUILTIN_SCOPE.get(name))
-    }
-
-    pub fn traits<'a>(&'a self) -> impl Iterator<Item = TraitId> + 'a {
-        self.items.values().filter_map(|r| match r.def.take_types() {
-            Some(ModuleDefId::TraitId(t)) => Some(t),
-            _ => None,
-        })
-    }
-
-    fn get_legacy_macro(&self, name: &Name) -> Option<MacroDefId> {
-        self.legacy_macros.get(name).copied()
-    }
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Default)]
-pub struct Resolution {
-    /// None for unresolved
-    pub def: PerNs,
-    /// ident by which this is imported into local scope.
-    pub import: Option<ImportId>,
-}
-
-impl Resolution {
-    pub(crate) fn from_macro(macro_: MacroDefId) -> Self {
-        Resolution { def: PerNs::macros(macro_), import: None }
-    }
-}
-
-#[derive(Debug, Clone)]
-struct ResolvePathResult {
-    resolved_def: PerNs,
-    segment_index: Option<usize>,
-    reached_fixedpoint: ReachedFixedPoint,
-}
-
-impl ResolvePathResult {
-    fn empty(reached_fixedpoint: ReachedFixedPoint) -> ResolvePathResult {
-        ResolvePathResult::with(PerNs::none(), reached_fixedpoint, None)
-    }
-
-    fn with(
-        resolved_def: PerNs,
-        reached_fixedpoint: ReachedFixedPoint,
-        segment_index: Option<usize>,
-    ) -> ResolvePathResult {
-        ResolvePathResult { resolved_def, reached_fixedpoint, segment_index }
-    }
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-enum ResolveMode {
-    Import,
-    Other,
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-enum ReachedFixedPoint {
-    Yes,
-    No,
-}
-
-impl CrateDefMap {
-    pub(crate) fn crate_def_map_query(
-        // Note that this doesn't have `+ AstDatabase`!
-        // This gurantess that `CrateDefMap` is stable across reparses.
-        db: &impl DefDatabase2,
-        krate: CrateId,
-    ) -> Arc<CrateDefMap> {
-        let _p = profile("crate_def_map_query");
-        let def_map = {
-            let crate_graph = db.crate_graph();
-            let edition = crate_graph.edition(krate);
-            let mut modules: Arena<CrateModuleId, ModuleData> = Arena::default();
-            let root = modules.alloc(ModuleData::default());
-            CrateDefMap {
-                krate,
-                edition,
-                extern_prelude: FxHashMap::default(),
-                prelude: None,
-                root,
-                modules,
-                poison_macros: FxHashSet::default(),
-                diagnostics: Vec::new(),
-            }
-        };
-        let def_map = collector::collect_defs(db, def_map);
-        Arc::new(def_map)
-    }
-
-    pub fn krate(&self) -> CrateId {
-        self.krate
-    }
-
-    pub fn root(&self) -> CrateModuleId {
-        self.root
-    }
-
-    pub fn prelude(&self) -> Option<ModuleId> {
-        self.prelude
-    }
-
-    pub fn extern_prelude(&self) -> &FxHashMap<Name, ModuleDefId> {
-        &self.extern_prelude
-    }
-
-    pub fn add_diagnostics(
-        &self,
-        db: &impl DefDatabase2,
-        module: CrateModuleId,
-        sink: &mut DiagnosticSink,
-    ) {
-        self.diagnostics.iter().for_each(|it| it.add_to(db, module, sink))
-    }
-
-    pub fn resolve_path(
-        &self,
-        db: &impl DefDatabase2,
-        original_module: CrateModuleId,
-        path: &Path,
-    ) -> (PerNs, Option<usize>) {
-        let res = self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path);
-        (res.resolved_def, res.segment_index)
-    }
-
-    // Returns Yes if we are sure that additions to `ItemMap` wouldn't change
-    // the result.
-    fn resolve_path_fp_with_macro(
-        &self,
-        db: &impl DefDatabase2,
-        mode: ResolveMode,
-        original_module: CrateModuleId,
-        path: &Path,
-    ) -> ResolvePathResult {
-        let mut segments = path.segments.iter().enumerate();
-        let mut curr_per_ns: PerNs = match path.kind {
-            PathKind::DollarCrate(krate) => {
-                if krate == self.krate {
-                    tested_by!(macro_dollar_crate_self);
-                    PerNs::types(ModuleId { krate: self.krate, module_id: self.root }.into())
-                } else {
-                    let def_map = db.crate_def_map(krate);
-                    let module = ModuleId { krate, module_id: def_map.root };
-                    tested_by!(macro_dollar_crate_other);
-                    PerNs::types(module.into())
-                }
-            }
-            PathKind::Crate => {
-                PerNs::types(ModuleId { krate: self.krate, module_id: self.root }.into())
-            }
-            PathKind::Self_ => {
-                PerNs::types(ModuleId { krate: self.krate, module_id: original_module }.into())
-            }
-            // plain import or absolute path in 2015: crate-relative with
-            // fallback to extern prelude (with the simplification in
-            // rust-lang/rust#57745)
-            // FIXME there must be a nicer way to write this condition
-            PathKind::Plain | PathKind::Abs
-                if self.edition == Edition::Edition2015
-                    && (path.kind == PathKind::Abs || mode == ResolveMode::Import) =>
-            {
-                let segment = match segments.next() {
-                    Some((_, segment)) => segment,
-                    None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
-                };
-                log::debug!("resolving {:?} in crate root (+ extern prelude)", segment);
-                self.resolve_name_in_crate_root_or_extern_prelude(&segment.name)
-            }
-            PathKind::Plain => {
-                let segment = match segments.next() {
-                    Some((_, segment)) => segment,
-                    None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
-                };
-                log::debug!("resolving {:?} in module", segment);
-                self.resolve_name_in_module(db, original_module, &segment.name)
-            }
-            PathKind::Super => {
-                if let Some(p) = self.modules[original_module].parent {
-                    PerNs::types(ModuleId { krate: self.krate, module_id: p }.into())
-                } else {
-                    log::debug!("super path in root module");
-                    return ResolvePathResult::empty(ReachedFixedPoint::Yes);
-                }
-            }
-            PathKind::Abs => {
-                // 2018-style absolute path -- only extern prelude
-                let segment = match segments.next() {
-                    Some((_, segment)) => segment,
-                    None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
-                };
-                if let Some(def) = self.extern_prelude.get(&segment.name) {
-                    log::debug!("absolute path {:?} resolved to crate {:?}", path, def);
-                    PerNs::types(*def)
-                } else {
-                    return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude
-                }
-            }
-            PathKind::Type(_) => {
-                // This is handled in `infer::infer_path_expr`
-                // The result returned here does not matter
-                return ResolvePathResult::empty(ReachedFixedPoint::Yes);
-            }
-        };
-
-        for (i, segment) in segments {
-            let curr = match curr_per_ns.take_types() {
-                Some(r) => r,
-                None => {
-                    // we still have path segments left, but the path so far
-                    // didn't resolve in the types namespace => no resolution
-                    // (don't break here because `curr_per_ns` might contain
-                    // something in the value namespace, and it would be wrong
-                    // to return that)
-                    return ResolvePathResult::empty(ReachedFixedPoint::No);
-                }
-            };
-            // resolve segment in curr
-
-            curr_per_ns = match curr {
-                ModuleDefId::ModuleId(module) => {
-                    if module.krate != self.krate {
-                        let path =
-                            Path { segments: path.segments[i..].to_vec(), kind: PathKind::Self_ };
-                        log::debug!("resolving {:?} in other crate", path);
-                        let defp_map = db.crate_def_map(module.krate);
-                        let (def, s) = defp_map.resolve_path(db, module.module_id, &path);
-                        return ResolvePathResult::with(
-                            def,
-                            ReachedFixedPoint::Yes,
-                            s.map(|s| s + i),
-                        );
-                    }
-
-                    // Since it is a qualified path here, it should not contains legacy macros
-                    match self[module.module_id].scope.get(&segment.name) {
-                        Some(res) => res.def,
-                        _ => {
-                            log::debug!("path segment {:?} not found", segment.name);
-                            return ResolvePathResult::empty(ReachedFixedPoint::No);
-                        }
-                    }
-                }
-                ModuleDefId::AdtId(AdtId::EnumId(e)) => {
-                    // enum variant
-                    tested_by!(can_import_enum_variant);
-                    let enum_data = db.enum_data(e);
-                    match enum_data.variant(&segment.name) {
-                        Some(local_id) => {
-                            let variant = EnumVariantId { parent: e, local_id };
-                            PerNs::both(variant.into(), variant.into())
-                        }
-                        None => {
-                            return ResolvePathResult::with(
-                                PerNs::types(e.into()),
-                                ReachedFixedPoint::Yes,
-                                Some(i),
-                            );
-                        }
-                    }
-                }
-                s => {
-                    // could be an inherent method call in UFCS form
-                    // (`Struct::method`), or some other kind of associated item
-                    log::debug!(
-                        "path segment {:?} resolved to non-module {:?}, but is not last",
-                        segment.name,
-                        curr,
-                    );
-
-                    return ResolvePathResult::with(
-                        PerNs::types(s),
-                        ReachedFixedPoint::Yes,
-                        Some(i),
-                    );
-                }
-            };
-        }
-        ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None)
-    }
-
-    fn resolve_name_in_crate_root_or_extern_prelude(&self, name: &Name) -> PerNs {
-        let from_crate_root =
-            self[self.root].scope.get(name).map_or_else(PerNs::none, |res| res.def);
-        let from_extern_prelude = self.resolve_name_in_extern_prelude(name);
-
-        from_crate_root.or(from_extern_prelude)
-    }
-
-    pub(crate) fn resolve_name_in_module(
-        &self,
-        db: &impl DefDatabase2,
-        module: CrateModuleId,
-        name: &Name,
-    ) -> PerNs {
-        // Resolve in:
-        //  - legacy scope of macro
-        //  - current module / scope
-        //  - extern prelude
-        //  - std prelude
-        let from_legacy_macro =
-            self[module].scope.get_legacy_macro(name).map_or_else(PerNs::none, PerNs::macros);
-        let from_scope = self[module].scope.get(name).map_or_else(PerNs::none, |res| res.def);
-        let from_extern_prelude =
-            self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it));
-        let from_prelude = self.resolve_in_prelude(db, name);
-
-        from_legacy_macro.or(from_scope).or(from_extern_prelude).or(from_prelude)
-    }
-
-    fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs {
-        self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it))
-    }
-
-    fn resolve_in_prelude(&self, db: &impl DefDatabase2, name: &Name) -> PerNs {
-        if let Some(prelude) = self.prelude {
-            let keep;
-            let def_map = if prelude.krate == self.krate {
-                self
-            } else {
-                // Extend lifetime
-                keep = db.crate_def_map(prelude.krate);
-                &keep
-            };
-            def_map[prelude.module_id].scope.get(name).map_or_else(PerNs::none, |res| res.def)
-        } else {
-            PerNs::none()
-        }
-    }
-}
-
-mod diagnostics {
-    use hir_expand::diagnostics::DiagnosticSink;
-    use ra_db::RelativePathBuf;
-    use ra_syntax::{ast, AstPtr};
-
-    use crate::{db::DefDatabase2, diagnostics::UnresolvedModule, nameres::CrateModuleId, AstId};
-
-    #[derive(Debug, PartialEq, Eq)]
-    pub(super) enum DefDiagnostic {
-        UnresolvedModule {
-            module: CrateModuleId,
-            declaration: AstId<ast::Module>,
-            candidate: RelativePathBuf,
-        },
-    }
-
-    impl DefDiagnostic {
-        pub(super) fn add_to(
-            &self,
-            db: &impl DefDatabase2,
-            target_module: CrateModuleId,
-            sink: &mut DiagnosticSink,
-        ) {
-            match self {
-                DefDiagnostic::UnresolvedModule { module, declaration, candidate } => {
-                    if *module != target_module {
-                        return;
-                    }
-                    let decl = declaration.to_node(db);
-                    sink.push(UnresolvedModule {
-                        file: declaration.file_id(),
-                        decl: AstPtr::new(&decl),
-                        candidate: candidate.clone(),
-                    })
-                }
-            }
-        }
-    }
-}
diff --git a/crates/ra_hir_def/src/nameres/mod_resolution.rs b/crates/ra_hir_def/src/nameres/mod_resolution.rs
index f6b0b8fb1e..7d7e2779aa 100644
--- a/crates/ra_hir_def/src/nameres/mod_resolution.rs
+++ b/crates/ra_hir_def/src/nameres/mod_resolution.rs
@@ -1,7 +1,8 @@
 //! This module resolves `mod foo;` declaration to file.
 use hir_expand::name::Name;
-use ra_db::{FileId, RelativePathBuf};
+use ra_db::FileId;
 use ra_syntax::SmolStr;
+use relative_path::RelativePathBuf;
 
 use crate::{db::DefDatabase2, HirFileId};
 
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs
index cb47fa317d..86c05d6028 100644
--- a/crates/ra_hir_def/src/nameres/raw.rs
+++ b/crates/ra_hir_def/src/nameres/raw.rs
@@ -14,7 +14,6 @@ use ra_syntax::{
     ast::{self, AttrsOwner, NameOwner},
     AstNode, AstPtr, SourceFile,
 };
-use test_utils::tested_by;
 
 use crate::{attr::Attr, db::DefDatabase2, path::Path, FileAstId, HirFileId, ModuleSource, Source};
 
@@ -298,7 +297,8 @@ impl RawItemsCollector {
             self.push_item(current_module, attrs, RawItemKind::Module(item));
             return;
         }
-        tested_by!(name_res_works_for_broken_modules);
+        // FIXME: restore this mark once we complete hir splitting
+        // tested_by!(name_res_works_for_broken_modules);
     }
 
     fn add_use_item(&mut self, current_module: Option<Module>, use_item: ast::UseItem) {
diff --git a/crates/ra_ide_api/Cargo.toml b/crates/ra_ide_api/Cargo.toml
index fa353b5dd8..bf6ef12f3f 100644
--- a/crates/ra_ide_api/Cargo.toml
+++ b/crates/ra_ide_api/Cargo.toml
@@ -12,6 +12,7 @@ format-buf = "1.0.0"
 itertools = "0.8.0"
 join_to_string = "0.1.3"
 log = "0.4.5"
+relative-path = "1.0.0"
 rayon = "1.0.2"
 fst = { version = "0.3.1", default-features = false }
 rustc-hash = "1.0"
diff --git a/crates/ra_ide_api/src/change.rs b/crates/ra_ide_api/src/change.rs
index 4416421ae0..39c5946c7f 100644
--- a/crates/ra_ide_api/src/change.rs
+++ b/crates/ra_ide_api/src/change.rs
@@ -4,13 +4,13 @@ use std::{fmt, sync::Arc, time};
 
 use ra_db::{
     salsa::{Database, Durability, SweepStrategy},
-    CrateGraph, CrateId, FileId, RelativePathBuf, SourceDatabase, SourceDatabaseExt, SourceRoot,
-    SourceRootId,
+    CrateGraph, CrateId, FileId, SourceDatabase, SourceDatabaseExt, SourceRoot, SourceRootId,
 };
 use ra_prof::{memory_usage, profile, Bytes};
 use ra_syntax::SourceFile;
 #[cfg(not(feature = "wasm"))]
 use rayon::prelude::*;
+use relative_path::RelativePathBuf;
 use rustc_hash::FxHashMap;
 
 use crate::{
diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs
index 09ca401794..9ac9768afb 100644
--- a/crates/ra_ide_api/src/completion/complete_path.rs
+++ b/crates/ra_ide_api/src/completion/complete_path.rs
@@ -18,15 +18,15 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
     match def {
         hir::ModuleDef::Module(module) => {
             let module_scope = module.scope(ctx.db);
-            for (name, def, import) in module_scope {
-                if let hir::ScopeDef::ModuleDef(hir::ModuleDef::BuiltinType(..)) = def {
+            for (name, res) in module_scope.entries() {
+                if let Some(hir::ModuleDef::BuiltinType(..)) = res.def.take_types() {
                     if ctx.use_item_syntax.is_some() {
                         tested_by!(dont_complete_primitive_in_use);
                         continue;
                     }
                 }
                 if Some(module) == ctx.module {
-                    if let Some(import) = import {
+                    if let Some(import) = res.import {
                         if let Either::A(use_tree) = module.import_source(ctx.db, import) {
                             if use_tree.syntax().text_range().contains_inclusive(ctx.offset) {
                                 // for `use self::foo<|>`, don't suggest `foo` as a completion
@@ -36,7 +36,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
                         }
                     }
                 }
-                acc.add_resolution(ctx, name.to_string(), &def);
+                acc.add_resolution(ctx, name.to_string(), &res.def.into());
             }
         }
         hir::ModuleDef::Adt(_) | hir::ModuleDef::TypeAlias(_) => {
diff --git a/crates/ra_ide_api/src/db.rs b/crates/ra_ide_api/src/db.rs
index c96465b6a3..785e71808b 100644
--- a/crates/ra_ide_api/src/db.rs
+++ b/crates/ra_ide_api/src/db.rs
@@ -4,9 +4,10 @@ use std::sync::Arc;
 
 use ra_db::{
     salsa::{self, Database, Durability},
-    Canceled, CheckCanceled, CrateId, FileId, FileLoader, FileLoaderDelegate, RelativePath,
-    SourceDatabase, SourceDatabaseExt, SourceRootId,
+    Canceled, CheckCanceled, CrateId, FileId, FileLoader, FileLoaderDelegate, SourceDatabase,
+    SourceDatabaseExt, SourceRootId,
 };
+use relative_path::RelativePath;
 use rustc_hash::FxHashMap;
 
 use crate::{
diff --git a/crates/ra_ide_api/src/diagnostics.rs b/crates/ra_ide_api/src/diagnostics.rs
index 2890a3d2b5..1f1f5cd742 100644
--- a/crates/ra_ide_api/src/diagnostics.rs
+++ b/crates/ra_ide_api/src/diagnostics.rs
@@ -4,7 +4,7 @@ use std::cell::RefCell;
 
 use hir::diagnostics::{AstDiagnostic, Diagnostic as _, DiagnosticSink};
 use itertools::Itertools;
-use ra_db::{RelativePath, SourceDatabase, SourceDatabaseExt};
+use ra_db::{SourceDatabase, SourceDatabaseExt};
 use ra_prof::profile;
 use ra_syntax::{
     algo,
@@ -12,6 +12,7 @@ use ra_syntax::{
     Location, SyntaxNode, TextRange, T,
 };
 use ra_text_edit::{TextEdit, TextEditBuilder};
+use relative_path::RelativePath;
 
 use crate::{db::RootDatabase, Diagnostic, FileId, FileSystemEdit, SourceChange, SourceFileEdit};
 
diff --git a/crates/ra_ide_api/src/mock_analysis.rs b/crates/ra_ide_api/src/mock_analysis.rs
index 2b1c96dbfd..80b71894cd 100644
--- a/crates/ra_ide_api/src/mock_analysis.rs
+++ b/crates/ra_ide_api/src/mock_analysis.rs
@@ -3,7 +3,7 @@
 use std::sync::Arc;
 
 use ra_cfg::CfgOptions;
-use ra_db::RelativePathBuf;
+use relative_path::RelativePathBuf;
 use test_utils::{extract_offset, extract_range, parse_fixture, CURSOR_MARKER};
 
 use crate::{
diff --git a/crates/ra_ide_api/src/references/rename.rs b/crates/ra_ide_api/src/references/rename.rs
index 11f81cbb32..a8783d7a0d 100644
--- a/crates/ra_ide_api/src/references/rename.rs
+++ b/crates/ra_ide_api/src/references/rename.rs
@@ -1,9 +1,10 @@
 //! FIXME: write short doc here
 
 use hir::ModuleSource;
-use ra_db::{RelativePath, RelativePathBuf, SourceDatabase, SourceDatabaseExt};
+use ra_db::{SourceDatabase, SourceDatabaseExt};
 use ra_syntax::{algo::find_node_at_offset, ast, AstNode, SyntaxNode};
 use ra_text_edit::TextEdit;
+use relative_path::{RelativePath, RelativePathBuf};
 
 use crate::{
     db::RootDatabase, FileId, FilePosition, FileSystemEdit, RangeInfo, SourceChange,
diff --git a/crates/ra_ide_api/src/source_change.rs b/crates/ra_ide_api/src/source_change.rs
index f5f7f8807c..4e63bbf6f0 100644
--- a/crates/ra_ide_api/src/source_change.rs
+++ b/crates/ra_ide_api/src/source_change.rs
@@ -3,8 +3,8 @@
 //!
 //! It can be viewed as a dual for `AnalysisChange`.
 
-use ra_db::RelativePathBuf;
 use ra_text_edit::TextEdit;
+use relative_path::RelativePathBuf;
 
 use crate::{FileId, FilePosition, SourceRootId, TextUnit};
 
diff --git a/crates/ra_mbe/src/lib.rs b/crates/ra_mbe/src/lib.rs
index afdbee84e3..15f0001755 100644
--- a/crates/ra_mbe/src/lib.rs
+++ b/crates/ra_mbe/src/lib.rs
@@ -42,6 +42,8 @@ pub use crate::syntax_bridge::{
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub struct MacroRules {
     pub(crate) rules: Vec<Rule>,
+    /// Highest id of the token we have in TokenMap
+    pub(crate) shift: u32,
 }
 
 #[derive(Clone, Debug, PartialEq, Eq)]
@@ -50,6 +52,38 @@ pub(crate) struct Rule {
     pub(crate) rhs: tt::Subtree,
 }
 
+// Find the max token id inside a subtree
+fn max_id(subtree: &tt::Subtree) -> Option<u32> {
+    subtree
+        .token_trees
+        .iter()
+        .filter_map(|tt| match tt {
+            tt::TokenTree::Subtree(subtree) => max_id(subtree),
+            tt::TokenTree::Leaf(tt::Leaf::Ident(ident))
+                if ident.id != tt::TokenId::unspecified() =>
+            {
+                Some(ident.id.0)
+            }
+            _ => None,
+        })
+        .max()
+}
+
+/// Shift given TokenTree token id
+fn shift_subtree(tt: &mut tt::Subtree, shift: u32) {
+    for t in tt.token_trees.iter_mut() {
+        match t {
+            tt::TokenTree::Leaf(leaf) => match leaf {
+                tt::Leaf::Ident(ident) if ident.id != tt::TokenId::unspecified() => {
+                    ident.id.0 += shift;
+                }
+                _ => (),
+            },
+            tt::TokenTree::Subtree(tt) => shift_subtree(tt, shift),
+        }
+    }
+}
+
 impl MacroRules {
     pub fn parse(tt: &tt::Subtree) -> Result<MacroRules, ParseError> {
         // Note: this parsing can be implemented using mbe machinery itself, by
@@ -72,10 +106,17 @@ impl MacroRules {
             validate(&rule.lhs)?;
         }
 
-        Ok(MacroRules { rules })
+        // Note that TokenId is started from zero,
+        // We have to add 1 to prevent duplication.
+        let shift = max_id(tt).map_or(0, |it| it + 1);
+        Ok(MacroRules { rules, shift })
     }
+
     pub fn expand(&self, tt: &tt::Subtree) -> Result<tt::Subtree, ExpandError> {
-        mbe_expander::expand(self, tt)
+        // apply shift
+        let mut tt = tt.clone();
+        shift_subtree(&mut tt, self.shift);
+        mbe_expander::expand(self, &tt)
     }
 }
 
diff --git a/crates/ra_syntax/src/ast/make.rs b/crates/ra_syntax/src/ast/make.rs
index 95062ef6c4..3d5f18bfae 100644
--- a/crates/ra_syntax/src/ast/make.rs
+++ b/crates/ra_syntax/src/ast/make.rs
@@ -110,23 +110,6 @@ pub fn match_arm_list(arms: impl Iterator<Item = ast::MatchArm>) -> ast::MatchAr
     }
 }
 
-pub fn let_match_early(expr: ast::Expr, path: &str, early_expression: &str) -> ast::LetStmt {
-    return from_text(&format!(
-        r#"let {} = match {} {{
-    {}(it) => it,
-    None => {},
-}};"#,
-        expr.syntax().text(),
-        expr.syntax().text(),
-        path,
-        early_expression
-    ));
-
-    fn from_text(text: &str) -> ast::LetStmt {
-        ast_from_text(&format!("fn f() {{ {} }}", text))
-    }
-}
-
 pub fn where_pred(path: ast::Path, bounds: impl Iterator<Item = ast::TypeBound>) -> ast::WherePred {
     let bounds = bounds.map(|b| b.syntax().to_string()).join(" + ");
     return from_text(&format!("{}: {}", path.syntax(), bounds));


Test patch:
diff --git a/crates/ra_hir_def/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs
similarity index 73%
rename from crates/ra_hir_def/src/nameres/tests.rs
rename to crates/ra_hir/src/nameres/tests.rs
index 52bd0aa91e..8c6b40aaf2 100644
--- a/crates/ra_hir_def/src/nameres/tests.rs
+++ b/crates/ra_hir/src/nameres/tests.rs
@@ -1,31 +1,35 @@
+mod macros;
 mod globs;
 mod incremental;
-mod macros;
-mod mod_resolution;
 mod primitives;
+mod mod_resolution;
 
 use std::sync::Arc;
 
 use insta::assert_snapshot;
-use ra_db::{fixture::WithFixture, SourceDatabase};
+use ra_db::SourceDatabase;
 use test_utils::covers;
 
-use crate::{db::DefDatabase2, nameres::*, test_db::TestDB, CrateModuleId};
+use crate::{
+    mock::{CrateGraphFixture, MockDatabase},
+    Crate,
+};
 
-fn def_map(fixtute: &str) -> String {
-    let dm = compute_crate_def_map(fixtute);
-    render_crate_def_map(&dm)
-}
+use super::*;
 
-fn compute_crate_def_map(fixture: &str) -> Arc<CrateDefMap> {
-    let db = TestDB::with_files(fixture);
-    let krate = db.crate_graph().iter().next().unwrap();
+fn compute_crate_def_map(fixture: &str, graph: Option<CrateGraphFixture>) -> Arc<CrateDefMap> {
+    let mut db = MockDatabase::with_files(fixture);
+    if let Some(graph) = graph {
+        db.set_crate_graph_from_fixture(graph);
+    }
+    let crate_id = db.crate_graph().iter().next().unwrap();
+    let krate = Crate { crate_id };
     db.crate_def_map(krate)
 }
 
 fn render_crate_def_map(map: &CrateDefMap) -> String {
     let mut buf = String::new();
-    go(&mut buf, map, "\ncrate", map.root());
+    go(&mut buf, map, "\ncrate", map.root);
     return buf.trim().to_string();
 
     fn go(buf: &mut String, map: &CrateDefMap, path: &str, module: CrateModuleId) {
@@ -66,6 +70,16 @@ fn render_crate_def_map(map: &CrateDefMap) -> String {
     }
 }
 
+fn def_map(fixtute: &str) -> String {
+    let dm = compute_crate_def_map(fixtute, None);
+    render_crate_def_map(&dm)
+}
+
+fn def_map_with_crate_graph(fixture: &str, graph: CrateGraphFixture) -> String {
+    let dm = compute_crate_def_map(fixture, Some(graph));
+    render_crate_def_map(&dm)
+}
+
 #[test]
 fn crate_def_map_smoke_test() {
     let map = def_map(
@@ -220,12 +234,12 @@ fn re_exports() {
 #[test]
 fn std_prelude() {
     covers!(std_prelude);
-    let map = def_map(
+    let map = def_map_with_crate_graph(
         "
-        //- /main.rs crate:main deps:test_crate
+        //- /main.rs
         use Foo::*;
 
-        //- /lib.rs crate:test_crate
+        //- /lib.rs
         mod prelude;
         #[prelude_import]
         use prelude::*;
@@ -233,6 +247,10 @@ fn std_prelude() {
         //- /prelude.rs
         pub enum Foo { Bar, Baz };
         ",
+        crate_graph! {
+            "main": ("/main.rs", ["test_crate"]),
+            "test_crate": ("/lib.rs", []),
+        },
     );
     assert_snapshot!(map, @r###"
         ⋮crate
@@ -261,9 +279,9 @@ fn can_import_enum_variant() {
 
 #[test]
 fn edition_2015_imports() {
-    let map = def_map(
+    let map = def_map_with_crate_graph(
         "
-        //- /main.rs crate:main deps:other_crate edition:2015
+        //- /main.rs
         mod foo;
         mod bar;
 
@@ -274,9 +292,13 @@ fn edition_2015_imports() {
         use bar::Bar;
         use other_crate::FromLib;
 
-        //- /lib.rs crate:other_crate edition:2018
+        //- /lib.rs
         struct FromLib;
         ",
+        crate_graph! {
+            "main": ("/main.rs", "2015", ["other_crate"]),
+            "other_crate": ("/lib.rs", "2018", []),
+        },
     );
 
     assert_snapshot!(map, @r###"
@@ -321,14 +343,18 @@ fn item_map_using_self() {
 
 #[test]
 fn item_map_across_crates() {
-    let map = def_map(
+    let map = def_map_with_crate_graph(
         "
-        //- /main.rs crate:main deps:test_crate
+        //- /main.rs
         use test_crate::Baz;
 
-        //- /lib.rs crate:test_crate
+        //- /lib.rs
         pub struct Baz;
         ",
+        crate_graph! {
+            "main": ("/main.rs", ["test_crate"]),
+            "test_crate": ("/lib.rs", []),
+        },
     );
 
     assert_snapshot!(map, @r###"
@@ -339,9 +365,9 @@ fn item_map_across_crates() {
 
 #[test]
 fn extern_crate_rename() {
-    let map = def_map(
+    let map = def_map_with_crate_graph(
         "
-        //- /main.rs crate:main deps:alloc
+        //- /main.rs
         extern crate alloc as alloc_crate;
 
         mod alloc;
@@ -350,9 +376,13 @@ fn extern_crate_rename() {
         //- /sync.rs
         use alloc_crate::Arc;
 
-        //- /lib.rs crate:alloc
+        //- /lib.rs
         struct Arc;
         ",
+        crate_graph! {
+            "main": ("/main.rs", ["alloc"]),
+            "alloc": ("/lib.rs", []),
+        },
     );
 
     assert_snapshot!(map, @r###"
@@ -367,9 +397,9 @@ fn extern_crate_rename() {
 
 #[test]
 fn extern_crate_rename_2015_edition() {
-    let map = def_map(
+    let map = def_map_with_crate_graph(
         "
-        //- /main.rs crate:main deps:alloc edition:2015
+        //- /main.rs
         extern crate alloc as alloc_crate;
 
         mod alloc;
@@ -378,9 +408,13 @@ fn extern_crate_rename_2015_edition() {
         //- /sync.rs
         use alloc_crate::Arc;
 
-        //- /lib.rs crate:alloc
+        //- /lib.rs
         struct Arc;
         ",
+        crate_graph! {
+            "main": ("/main.rs", "2015", ["alloc"]),
+            "alloc": ("/lib.rs", []),
+        },
     );
 
     assert_snapshot!(map,
@@ -397,21 +431,24 @@ fn extern_crate_rename_2015_edition() {
 
 #[test]
 fn import_across_source_roots() {
-    let map = def_map(
+    let map = def_map_with_crate_graph(
         "
-        //- /main.rs crate:main deps:test_crate
-        use test_crate::a::b::C;
-
-        //- root /test_crate/
-
-        //- /test_crate/lib.rs crate:test_crate
+        //- /lib.rs
         pub mod a {
             pub mod b {
                 pub struct C;
             }
         }
 
+        //- root /main/
+
+        //- /main/main.rs
+        use test_crate::a::b::C;
         ",
+        crate_graph! {
+            "main": ("/main/main.rs", ["test_crate"]),
+            "test_crate": ("/lib.rs", []),
+        },
     );
 
     assert_snapshot!(map, @r###"
@@ -422,12 +459,12 @@ fn import_across_source_roots() {
 
 #[test]
 fn reexport_across_crates() {
-    let map = def_map(
+    let map = def_map_with_crate_graph(
         "
-        //- /main.rs crate:main deps:test_crate
+        //- /main.rs
         use test_crate::Baz;
 
-        //- /lib.rs crate:test_crate
+        //- /lib.rs
         pub use foo::Baz;
 
         mod foo;
@@ -435,6 +472,10 @@ fn reexport_across_crates() {
         //- /foo.rs
         pub struct Baz;
         ",
+        crate_graph! {
+            "main": ("/main.rs", ["test_crate"]),
+            "test_crate": ("/lib.rs", []),
+        },
     );
 
     assert_snapshot!(map, @r###"
@@ -445,15 +486,19 @@ fn reexport_across_crates() {
 
 #[test]
 fn values_dont_shadow_extern_crates() {
-    let map = def_map(
+    let map = def_map_with_crate_graph(
         "
-        //- /main.rs crate:main deps:foo
+        //- /main.rs
         fn foo() {}
         use foo::Bar;
 
-        //- /foo/lib.rs crate:foo
+        //- /foo/lib.rs
         pub struct Bar;
         ",
+        crate_graph! {
+            "main": ("/main.rs", ["foo"]),
+            "foo": ("/foo/lib.rs", []),
+        },
     );
 
     assert_snapshot!(map, @r###"
@@ -465,12 +510,11 @@ fn values_dont_shadow_extern_crates() {
 
 #[test]
 fn cfg_not_test() {
-    let map = def_map(
+    let map = def_map_with_crate_graph(
         r#"
-        //- /main.rs crate:main deps:std
+        //- /main.rs
         use {Foo, Bar, Baz};
-
-        //- /lib.rs crate:std
+        //- /lib.rs
         #[prelude_import]
         pub use self::prelude::*;
         mod prelude {
@@ -482,6 +526,10 @@ fn cfg_not_test() {
             pub struct Baz;
         }
         "#,
+        crate_graph! {
+            "main": ("/main.rs", ["std"]),
+            "std": ("/lib.rs", []),
+        },
     );
 
     assert_snapshot!(map, @r###"
@@ -494,12 +542,11 @@ fn cfg_not_test() {
 
 #[test]
 fn cfg_test() {
-    let map = def_map(
+    let map = def_map_with_crate_graph(
         r#"
-        //- /main.rs crate:main deps:std
+        //- /main.rs
         use {Foo, Bar, Baz};
-
-        //- /lib.rs crate:std cfg:test,feature=foo,feature=bar,opt=42
+        //- /lib.rs
         #[prelude_import]
         pub use self::prelude::*;
         mod prelude {
@@ -511,6 +558,15 @@ fn cfg_test() {
             pub struct Baz;
         }
         "#,
+        crate_graph! {
+            "main": ("/main.rs", ["std"]),
+            "std": ("/lib.rs", [], cfg = {
+                "test",
+                "feature" = "foo",
+                "feature" = "bar",
+                "opt" = "42",
+            }),
+        },
     );
 
     assert_snapshot!(map, @r###"
diff --git a/crates/ra_hir_def/src/nameres/tests/globs.rs b/crates/ra_hir/src/nameres/tests/globs.rs
similarity index 88%
rename from crates/ra_hir_def/src/nameres/tests/globs.rs
rename to crates/ra_hir/src/nameres/tests/globs.rs
index 5b03fe3650..7ac22b47b8 100644
--- a/crates/ra_hir_def/src/nameres/tests/globs.rs
+++ b/crates/ra_hir/src/nameres/tests/globs.rs
@@ -76,14 +76,18 @@ fn glob_2() {
 #[test]
 fn glob_across_crates() {
     covers!(glob_across_crates);
-    let map = def_map(
+    let map = def_map_with_crate_graph(
         "
-        //- /main.rs crate:main deps:test_crate
+        //- /main.rs
         use test_crate::*;
 
-        //- /lib.rs crate:test_crate
+        //- /lib.rs
         pub struct Baz;
         ",
+        crate_graph! {
+            "main": ("/main.rs", ["test_crate"]),
+            "test_crate": ("/lib.rs", []),
+        },
     );
     assert_snapshot!(map, @r###"
    ⋮crate
diff --git a/crates/ra_hir_def/src/nameres/tests/incremental.rs b/crates/ra_hir/src/nameres/tests/incremental.rs
similarity index 74%
rename from crates/ra_hir_def/src/nameres/tests/incremental.rs
rename to crates/ra_hir/src/nameres/tests/incremental.rs
index 80dcec62f0..af9c397602 100644
--- a/crates/ra_hir_def/src/nameres/tests/incremental.rs
+++ b/crates/ra_hir/src/nameres/tests/incremental.rs
@@ -1,12 +1,13 @@
+use super::*;
+
 use std::sync::Arc;
 
 use ra_db::{SourceDatabase, SourceDatabaseExt};
 
-use super::*;
-
 fn check_def_map_is_not_recomputed(initial: &str, file_change: &str) {
-    let (mut db, pos) = TestDB::with_position(initial);
-    let krate = db.crate_graph().iter().next().unwrap();
+    let (mut db, pos) = MockDatabase::with_position(initial);
+    let crate_id = db.crate_graph().iter().next().unwrap();
+    let krate = Crate { crate_id };
     {
         let events = db.log_executed(|| {
             db.crate_def_map(krate);
@@ -91,7 +92,7 @@ fn adding_inner_items_should_not_invalidate_def_map() {
 
 #[test]
 fn typing_inside_a_macro_should_not_invalidate_def_map() {
-    let (mut db, pos) = TestDB::with_position(
+    let (mut db, pos) = MockDatabase::with_position(
         "
         //- /lib.rs
         macro_rules! m {
@@ -111,12 +112,15 @@ fn typing_inside_a_macro_should_not_invalidate_def_map() {
         m!(X);
         ",
     );
-    let krate = db.crate_graph().iter().next().unwrap();
     {
         let events = db.log_executed(|| {
-            let crate_def_map = db.crate_def_map(krate);
-            let (_, module_data) = crate_def_map.modules.iter().last().unwrap();
-            assert_eq!(module_data.scope.items.len(), 1);
+            let src = crate::Source {
+                file_id: pos.file_id.into(),
+                ast: crate::ModuleSource::new(&db, Some(pos.file_id), None),
+            };
+            let module = crate::Module::from_definition(&db, src).unwrap();
+            let decls = module.declarations(&db);
+            assert_eq!(decls.len(), 18);
         });
         assert!(format!("{:?}", events).contains("crate_def_map"), "{:#?}", events)
     }
@@ -124,9 +128,13 @@ fn typing_inside_a_macro_should_not_invalidate_def_map() {
 
     {
         let events = db.log_executed(|| {
-            let crate_def_map = db.crate_def_map(krate);
-            let (_, module_data) = crate_def_map.modules.iter().last().unwrap();
-            assert_eq!(module_data.scope.items.len(), 1);
+            let src = crate::Source {
+                file_id: pos.file_id.into(),
+                ast: crate::ModuleSource::new(&db, Some(pos.file_id), None),
+            };
+            let module = crate::Module::from_definition(&db, src).unwrap();
+            let decls = module.declarations(&db);
+            assert_eq!(decls.len(), 18);
         });
         assert!(!format!("{:?}", events).contains("crate_def_map"), "{:#?}", events)
     }
diff --git a/crates/ra_hir_def/src/nameres/tests/macros.rs b/crates/ra_hir/src/nameres/tests/macros.rs
similarity index 86%
rename from crates/ra_hir_def/src/nameres/tests/macros.rs
rename to crates/ra_hir/src/nameres/tests/macros.rs
index 704065633a..4f52ad2c54 100644
--- a/crates/ra_hir_def/src/nameres/tests/macros.rs
+++ b/crates/ra_hir/src/nameres/tests/macros.rs
@@ -71,16 +71,16 @@ fn macro_rules_can_define_modules() {
 
 #[test]
 fn macro_rules_from_other_crates_are_visible() {
-    let map = def_map(
+    let map = def_map_with_crate_graph(
         "
-        //- /main.rs crate:main deps:foo
+        //- /main.rs
         foo::structs!(Foo, Bar)
         mod bar;
 
         //- /bar.rs
         use crate::*;
 
-        //- /lib.rs crate:foo
+        //- /lib.rs
         #[macro_export]
         macro_rules! structs {
             ($($i:ident),*) => {
@@ -88,6 +88,10 @@ fn macro_rules_from_other_crates_are_visible() {
             }
         }
         ",
+        crate_graph! {
+            "main": ("/main.rs", ["foo"]),
+            "foo": ("/lib.rs", []),
+        },
     );
     assert_snapshot!(map, @r###"
    ⋮crate
@@ -104,16 +108,16 @@ fn macro_rules_from_other_crates_are_visible() {
 
 #[test]
 fn macro_rules_export_with_local_inner_macros_are_visible() {
-    let map = def_map(
+    let map = def_map_with_crate_graph(
         "
-        //- /main.rs crate:main deps:foo
+        //- /main.rs
         foo::structs!(Foo, Bar)
         mod bar;
 
         //- /bar.rs
         use crate::*;
 
-        //- /lib.rs crate:foo
+        //- /lib.rs
         #[macro_export(local_inner_macros)]
         macro_rules! structs {
             ($($i:ident),*) => {
@@ -121,6 +125,10 @@ fn macro_rules_export_with_local_inner_macros_are_visible() {
             }
         }
         ",
+        crate_graph! {
+            "main": ("/main.rs", ["foo"]),
+            "foo": ("/lib.rs", []),
+        },
     );
     assert_snapshot!(map, @r###"
    ⋮crate
@@ -137,9 +145,9 @@ fn macro_rules_export_with_local_inner_macros_are_visible() {
 
 #[test]
 fn unexpanded_macro_should_expand_by_fixedpoint_loop() {
-    let map = def_map(
+    let map = def_map_with_crate_graph(
         "
-        //- /main.rs crate:main deps:foo
+        //- /main.rs
         macro_rules! baz {
             () => {
                 use foo::bar;
@@ -150,7 +158,7 @@ fn unexpanded_macro_should_expand_by_fixedpoint_loop() {
         bar!();
         baz!();
 
-        //- /lib.rs crate:foo
+        //- /lib.rs
         #[macro_export]
         macro_rules! foo {
             () => {
@@ -164,6 +172,10 @@ fn unexpanded_macro_should_expand_by_fixedpoint_loop() {
             }
         }
         ",
+        crate_graph! {
+            "main": ("/main.rs", ["foo"]),
+            "foo": ("/lib.rs", []),
+        },
     );
     assert_snapshot!(map, @r###"
    ⋮crate
@@ -176,9 +188,9 @@ fn unexpanded_macro_should_expand_by_fixedpoint_loop() {
 #[test]
 fn macro_rules_from_other_crates_are_visible_with_macro_use() {
     covers!(macro_rules_from_other_crates_are_visible_with_macro_use);
-    let map = def_map(
+    let map = def_map_with_crate_graph(
         "
-        //- /main.rs crate:main deps:foo
+        //- /main.rs
         structs!(Foo);
         structs_priv!(Bar);
         structs_not_exported!(MacroNotResolved1);
@@ -193,7 +205,7 @@ fn macro_rules_from_other_crates_are_visible_with_macro_use() {
         structs!(Baz);
         crate::structs!(MacroNotResolved3);
 
-        //- /lib.rs crate:foo
+        //- /lib.rs
         #[macro_export]
         macro_rules! structs {
             ($i:ident) => { struct $i; }
@@ -210,6 +222,10 @@ fn macro_rules_from_other_crates_are_visible_with_macro_use() {
             }
         }
         ",
+        crate_graph! {
+            "main": ("/main.rs", ["foo"]),
+            "foo": ("/lib.rs", []),
+        },
     );
     assert_snapshot!(map, @r###"
    ⋮crate
@@ -226,9 +242,9 @@ fn macro_rules_from_other_crates_are_visible_with_macro_use() {
 #[test]
 fn prelude_is_macro_use() {
     covers!(prelude_is_macro_use);
-    let map = def_map(
+    let map = def_map_with_crate_graph(
         "
-        //- /main.rs crate:main deps:foo
+        //- /main.rs
         structs!(Foo);
         structs_priv!(Bar);
         structs_outside!(Out);
@@ -240,7 +256,7 @@ fn prelude_is_macro_use() {
         structs!(Baz);
         crate::structs!(MacroNotResolved3);
 
-        //- /lib.rs crate:foo
+        //- /lib.rs
         #[prelude_import]
         use self::prelude::*;
 
@@ -263,6 +279,10 @@ fn prelude_is_macro_use() {
             ($i:ident) => { struct $i; }
         }
         ",
+        crate_graph! {
+            "main": ("/main.rs", ["foo"]),
+            "foo": ("/lib.rs", []),
+        },
     );
     assert_snapshot!(map, @r###"
    ⋮crate
@@ -427,16 +447,16 @@ fn type_value_macro_live_in_different_scopes() {
 
 #[test]
 fn macro_use_can_be_aliased() {
-    let map = def_map(
+    let map = def_map_with_crate_graph(
         "
-        //- /main.rs crate:main deps:foo
+        //- /main.rs
         #[macro_use]
         extern crate foo;
 
         foo!(Direct);
         bar!(Alias);
 
-        //- /lib.rs crate:foo
+        //- /lib.rs
         use crate::foo as bar;
 
         mod m {
@@ -446,6 +466,10 @@ fn macro_use_can_be_aliased() {
             }
         }
         ",
+        crate_graph! {
+            "main": ("/main.rs", ["foo"]),
+            "foo": ("/lib.rs", []),
+        },
     );
     assert_snapshot!(map, @r###"
         ⋮crate
@@ -509,9 +533,9 @@ fn path_qualified_macros() {
 fn macro_dollar_crate_is_correct_in_item() {
     covers!(macro_dollar_crate_self);
     covers!(macro_dollar_crate_other);
-    let map = def_map(
+    let map = def_map_with_crate_graph(
         "
-        //- /main.rs crate:main deps:foo
+        //- /main.rs
         #[macro_use]
         extern crate foo;
 
@@ -530,7 +554,7 @@ fn macro_dollar_crate_is_correct_in_item() {
         not_current1!();
         foo::not_current2!();
 
-        //- /lib.rs crate:foo
+        //- /lib.rs
         mod m {
             #[macro_export]
             macro_rules! not_current1 {
@@ -550,6 +574,10 @@ fn macro_dollar_crate_is_correct_in_item() {
         struct Bar;
         struct Baz;
         ",
+        crate_graph! {
+            "main": ("/main.rs", ["foo"]),
+            "foo": ("/lib.rs", []),
+        },
     );
     assert_snapshot!(map, @r###"
         ⋮crate
@@ -568,12 +596,12 @@ fn macro_dollar_crate_is_correct_in_item() {
 fn macro_dollar_crate_is_correct_in_indirect_deps() {
     covers!(macro_dollar_crate_other);
     // From std
-    let map = def_map(
+    let map = def_map_with_crate_graph(
         r#"
-        //- /main.rs crate:main deps:std
+        //- /main.rs
         foo!();
 
-        //- /std.rs crate:std deps:core
+        //- /std.rs
         #[prelude_import]
         use self::prelude::*;
 
@@ -584,7 +612,7 @@ fn macro_dollar_crate_is_correct_in_indirect_deps() {
         #[macro_use]
         mod std_macros;
 
-        //- /core.rs crate:core
+        //- /core.rs
         #[macro_export]
         macro_rules! foo {
             () => {
@@ -594,6 +622,11 @@ fn macro_dollar_crate_is_correct_in_indirect_deps() {
 
         pub struct bar;
         "#,
+        crate_graph! {
+            "main": ("/main.rs", ["std"]),
+            "std": ("/std.rs", ["core"]),
+            "core": ("/core.rs", []),
+        },
     );
     assert_snapshot!(map, @r###"
         ⋮crate
diff --git a/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs b/crates/ra_hir/src/nameres/tests/mod_resolution.rs
similarity index 93%
rename from crates/ra_hir_def/src/nameres/tests/mod_resolution.rs
rename to crates/ra_hir/src/nameres/tests/mod_resolution.rs
index dee364a142..abfe8b1c34 100644
--- a/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs
+++ b/crates/ra_hir/src/nameres/tests/mod_resolution.rs
@@ -2,7 +2,7 @@ use super::*;
 
 #[test]
 fn name_res_works_for_broken_modules() {
-    covers!(name_res_works_for_broken_modules);
+    // covers!(name_res_works_for_broken_modules);
     let map = def_map(
         "
         //- /lib.rs
@@ -54,15 +54,18 @@ fn nested_module_resolution() {
 
 #[test]
 fn module_resolution_works_for_non_standard_filenames() {
-    let map = def_map(
+    let map = def_map_with_crate_graph(
         "
-        //- /my_library.rs crate:my_library
+        //- /my_library.rs
         mod foo;
         use self::foo::Bar;
 
         //- /foo/mod.rs
         pub struct Bar;
         ",
+        crate_graph! {
+            "my_library": ("/my_library.rs", []),
+        },
     );
 
     assert_snapshot!(map, @r###"
@@ -647,7 +650,7 @@ fn module_resolution_decl_inside_inline_module_in_non_crate_root_2() {
 
 #[test]
 fn unresolved_module_diagnostics() {
-    let db = TestDB::with_files(
+    let diagnostics = MockDatabase::with_files(
         r"
         //- /lib.rs
         mod foo;
@@ -655,37 +658,11 @@ fn unresolved_module_diagnostics() {
         mod baz {}
         //- /foo.rs
         ",
-    );
-    let krate = db.crate_graph().iter().next().unwrap();
-
-    let crate_def_map = db.crate_def_map(krate);
-
-    insta::assert_debug_snapshot!(
-        crate_def_map.diagnostics,
-        @r###"
-    [
-        UnresolvedModule {
-            module: CrateModuleId(
-                0,
-            ),
-            declaration: AstId {
-                file_id: HirFileId(
-                    FileId(
-                        FileId(
-                            0,
-                        ),
-                    ),
-                ),
-                file_ast_id: FileAstId {
-                    raw: ErasedFileAstId(
-                        1,
-                    ),
-                    _ty: PhantomData,
-                },
-            },
-            candidate: "bar.rs",
-        },
-    ]
+    )
+    .diagnostics();
+
+    assert_snapshot!(diagnostics, @r###"
+    "mod bar;": unresolved module
     "###
     );
 }
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 4b7e34878a..bfef48b161 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -2,7 +2,8 @@ use std::fmt::Write;
 use std::sync::Arc;
 
 use insta::assert_snapshot;
-use ra_db::{fixture::WithFixture, salsa::Database, FilePosition, SourceDatabase};
+
+use ra_db::{salsa::Database, FilePosition, SourceDatabase};
 use ra_syntax::{
     algo,
     ast::{self, AstNode},
@@ -24,9 +25,9 @@ mod coercion;
 
 #[test]
 fn cfg_impl_block() {
-    let (db, pos) = MockDatabase::with_position(
+    let (mut db, pos) = MockDatabase::with_position(
         r#"
-//- /main.rs crate:main deps:foo cfg:test
+//- /main.rs
 use foo::S as T;
 struct S;
 
@@ -45,7 +46,7 @@ fn test() {
     t<|>;
 }
 
-//- /foo.rs crate:foo
+//- /foo.rs
 struct S;
 
 #[cfg(not(test))]
@@ -59,14 +60,18 @@ impl S {
 }
 "#,
     );
+    db.set_crate_graph_from_fixture(crate_graph! {
+        "main": ("/main.rs", ["foo"], cfg = { "test" }),
+        "foo": ("/foo.rs", []),
+    });
     assert_eq!("(i32, {unknown}, i32, {unknown})", type_at_pos(&db, pos));
 }
 
 #[test]
 fn infer_await() {
-    let (db, pos) = MockDatabase::with_position(
+    let (mut db, pos) = MockDatabase::with_position(
         r#"
-//- /main.rs crate:main deps:std
+//- /main.rs
 
 struct IntFuture;
 
@@ -80,7 +85,7 @@ fn test() {
     v<|>;
 }
 
-//- /std.rs crate:std
+//- /std.rs
 #[prelude_import] use future::*;
 mod future {
     trait Future {
@@ -90,14 +95,18 @@ mod future {
 
 "#,
     );
+    db.set_crate_graph_from_fixture(crate_graph! {
+        "main": ("/main.rs", ["std"]),
+        "std": ("/std.rs", []),
+    });
     assert_eq!("u64", type_at_pos(&db, pos));
 }
 
 #[test]
 fn infer_box() {
-    let (db, pos) = MockDatabase::with_position(
+    let (mut db, pos) = MockDatabase::with_position(
         r#"
-//- /main.rs crate:main deps:std
+//- /main.rs
 
 fn test() {
     let x = box 1;
@@ -105,7 +114,7 @@ fn test() {
     t<|>;
 }
 
-//- /std.rs crate:std
+//- /std.rs
 #[prelude_import] use prelude::*;
 mod prelude {}
 
@@ -117,6 +126,10 @@ mod boxed {
 
 "#,
     );
+    db.set_crate_graph_from_fixture(crate_graph! {
+        "main": ("/main.rs", ["std"]),
+        "std": ("/std.rs", []),
+    });
     assert_eq!("(Box<i32>, Box<Box<i32>>, Box<&i32>, Box<[i32;_]>)", type_at_pos(&db, pos));
 }
 
@@ -141,9 +154,9 @@ fn test() {
 
 #[test]
 fn infer_try() {
-    let (db, pos) = MockDatabase::with_position(
+    let (mut db, pos) = MockDatabase::with_position(
         r#"
-//- /main.rs crate:main deps:std
+//- /main.rs
 
 fn test() {
     let r: Result<i32, u64> = Result::Ok(1);
@@ -151,7 +164,7 @@ fn test() {
     v<|>;
 }
 
-//- /std.rs crate:std
+//- /std.rs
 
 #[prelude_import] use ops::*;
 mod ops {
@@ -176,14 +189,18 @@ mod result {
 
 "#,
     );
+    db.set_crate_graph_from_fixture(crate_graph! {
+        "main": ("/main.rs", ["std"]),
+        "std": ("/std.rs", []),
+    });
     assert_eq!("i32", type_at_pos(&db, pos));
 }
 
 #[test]
 fn infer_for_loop() {
-    let (db, pos) = MockDatabase::with_position(
+    let (mut db, pos) = MockDatabase::with_position(
         r#"
-//- /main.rs crate:main deps:std
+//- /main.rs
 
 use std::collections::Vec;
 
@@ -195,7 +212,7 @@ fn test() {
     }
 }
 
-//- /std.rs crate:std
+//- /std.rs
 
 #[prelude_import] use iter::*;
 mod iter {
@@ -217,6 +234,10 @@ mod collections {
 }
 "#,
     );
+    db.set_crate_graph_from_fixture(crate_graph! {
+        "main": ("/main.rs", ["std"]),
+        "std": ("/std.rs", []),
+    });
     assert_eq!("&str", type_at_pos(&db, pos));
 }
 
@@ -2484,15 +2505,15 @@ pub fn main_loop() {
 
 #[test]
 fn cross_crate_associated_method_call() {
-    let (db, pos) = MockDatabase::with_position(
+    let (mut db, pos) = MockDatabase::with_position(
         r#"
-//- /main.rs crate:main deps:other_crate
+//- /main.rs
 fn test() {
     let x = other_crate::foo::S::thing();
     x<|>;
 }
 
-//- /lib.rs crate:other_crate
+//- /lib.rs
 mod foo {
     struct S;
     impl S {
@@ -2501,6 +2522,10 @@ mod foo {
 }
 "#,
     );
+    db.set_crate_graph_from_fixture(crate_graph! {
+        "main": ("/main.rs", ["other_crate"]),
+        "other_crate": ("/lib.rs", []),
+    });
     assert_eq!("i128", type_at_pos(&db, pos));
 }
 
@@ -3378,15 +3403,16 @@ fn test() { S.foo()<|>; }
 
 #[test]
 fn infer_macro_with_dollar_crate_is_correct_in_expr() {
-    let (db, pos) = MockDatabase::with_position(
+    covers!(macro_dollar_crate_other);
+    let (mut db, pos) = MockDatabase::with_position(
         r#"
-//- /main.rs crate:main deps:foo
+//- /main.rs
 fn test() {
     let x = (foo::foo!(1), foo::foo!(2));
     x<|>;
 }
 
-//- /lib.rs crate:foo
+//- /lib.rs
 #[macro_export]
 macro_rules! foo {
     (1) => { $crate::bar!() };
@@ -3401,6 +3427,10 @@ macro_rules! bar {
 pub fn baz() -> usize { 31usize }
 "#,
     );
+    db.set_crate_graph_from_fixture(crate_graph! {
+        "main": ("/main.rs", ["foo"]),
+        "foo": ("/lib.rs", []),
+    });
     assert_eq!("(i32, usize)", type_at_pos(&db, pos));
 }
 
@@ -3482,9 +3512,9 @@ fn test() { (&S).foo()<|>; }
 
 #[test]
 fn method_resolution_trait_from_prelude() {
-    let (db, pos) = MockDatabase::with_position(
+    let (mut db, pos) = MockDatabase::with_position(
         r#"
-//- /main.rs crate:main deps:other_crate
+//- /main.rs
 struct S;
 impl Clone for S {}
 
@@ -3492,7 +3522,7 @@ fn test() {
     S.clone()<|>;
 }
 
-//- /lib.rs crate:other_crate
+//- /lib.rs
 #[prelude_import] use foo::*;
 
 mod foo {
@@ -3502,6 +3532,10 @@ mod foo {
 }
 "#,
     );
+    db.set_crate_graph_from_fixture(crate_graph! {
+        "main": ("/main.rs", ["other_crate"]),
+        "other_crate": ("/lib.rs", []),
+    });
     assert_eq!("S", type_at_pos(&db, pos));
 }
 
diff --git a/crates/ra_hir_def/src/test_db.rs b/crates/ra_hir_def/src/test_db.rs
deleted file mode 100644
index 8ee8e40d08..0000000000
--- a/crates/ra_hir_def/src/test_db.rs
+++ /dev/null
@@ -1,75 +0,0 @@
-//! Database used for testing `hir_def`.
-
-use std::{
-    panic,
-    sync::{Arc, Mutex},
-};
-
-use ra_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, RelativePath};
-
-#[salsa::database(
-    ra_db::SourceDatabaseExtStorage,
-    ra_db::SourceDatabaseStorage,
-    hir_expand::db::AstDatabaseStorage,
-    crate::db::InternDatabaseStorage,
-    crate::db::DefDatabase2Storage
-)]
-#[derive(Debug, Default)]
-pub struct TestDB {
-    runtime: salsa::Runtime<TestDB>,
-    events: Mutex<Option<Vec<salsa::Event<TestDB>>>>,
-}
-
-impl salsa::Database for TestDB {
-    fn salsa_runtime(&self) -> &salsa::Runtime<Self> {
-        &self.runtime
-    }
-
-    fn salsa_event(&self, event: impl Fn() -> salsa::Event<TestDB>) {
-        let mut events = self.events.lock().unwrap();
-        if let Some(events) = &mut *events {
-            events.push(event());
-        }
-    }
-}
-
-impl panic::RefUnwindSafe for TestDB {}
-
-impl FileLoader for TestDB {
-    fn file_text(&self, file_id: FileId) -> Arc<String> {
-        FileLoaderDelegate(self).file_text(file_id)
-    }
-    fn resolve_relative_path(
-        &self,
-        anchor: FileId,
-        relative_path: &RelativePath,
-    ) -> Option<FileId> {
-        FileLoaderDelegate(self).resolve_relative_path(anchor, relative_path)
-    }
-    fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>> {
-        FileLoaderDelegate(self).relevant_crates(file_id)
-    }
-}
-
-impl TestDB {
-    pub fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event<TestDB>> {
-        *self.events.lock().unwrap() = Some(Vec::new());
-        f();
-        self.events.lock().unwrap().take().unwrap()
-    }
-
-    pub fn log_executed(&self, f: impl FnOnce()) -> Vec<String> {
-        let events = self.log(f);
-        events
-            .into_iter()
-            .filter_map(|e| match e.kind {
-                // This pretty horrible, but `Debug` is the only way to inspect
-                // QueryDescriptor at the moment.
-                salsa::EventKind::WillExecute { database_key } => {
-                    Some(format!("{:?}", database_key))
-                }
-                _ => None,
-            })
-            .collect()
-    }
-}
diff --git a/crates/ra_mbe/src/tests.rs b/crates/ra_mbe/src/tests.rs
index f34ab52e19..a23e3afe3e 100644
--- a/crates/ra_mbe/src/tests.rs
+++ b/crates/ra_mbe/src/tests.rs
@@ -58,6 +58,33 @@ mod rule_parsing {
 // * Port the test to rust and add it to this module
 // * Make it pass :-)
 
+#[test]
+fn test_token_id_shift() {
+    let macro_definition = r#"
+macro_rules! foobar {
+    ($e:ident) => { foo bar $e }
+}
+"#;
+    let rules = create_rules(macro_definition);
+    let expansion = expand(&rules, "foobar!(baz);");
+
+    fn get_id(t: &tt::TokenTree) -> Option<u32> {
+        if let tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) = t {
+            return Some(ident.id.0);
+        }
+        None
+    }
+
+    assert_eq!(expansion.token_trees.len(), 3);
+    // ($e:ident) => { foo bar $e }
+    //   0 1            2   3   4
+    assert_eq!(get_id(&expansion.token_trees[0]), Some(2));
+    assert_eq!(get_id(&expansion.token_trees[1]), Some(3));
+
+    // So baz should be 5
+    assert_eq!(get_id(&expansion.token_trees[2]), Some(5));
+}
+
 #[test]
 fn test_convert_tt() {
     let macro_definition = r#"
diff --git a/xtask/tests/tidy-tests/docs.rs b/xtask/tests/tidy-tests/docs.rs
index 227937f462..6a629ce63e 100644
--- a/xtask/tests/tidy-tests/docs.rs
+++ b/xtask/tests/tidy-tests/docs.rs
@@ -36,7 +36,6 @@ fn is_hidden(entry: &DirEntry) -> bool {
 fn no_docs_comments() {
     let crates = project_root().join("crates");
     let iter = WalkDir::new(crates);
-    let mut missing_docs = Vec::new();
     for f in iter.into_iter().filter_entry(|e| !is_hidden(e)) {
         let f = f.unwrap();
         if f.file_type().is_dir() {
@@ -55,14 +54,12 @@ fn no_docs_comments() {
         let mut line = String::new();
         reader.read_line(&mut line).unwrap();
         if !line.starts_with("//!") {
-            missing_docs.push(f.path().display().to_string());
+            panic!(
+                "\nMissing docs strings\n\
+                 module: {}\n\
+                 Need add doc for module\n",
+                f.path().display()
+            )
         }
     }
-    if !missing_docs.is_empty() {
-        panic!(
-            "\nMissing docs strings\n\n\
-             modules:\n{}\n\n",
-            missing_docs.join("\n")
-        )
-    }
 }