diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs
index ef69ef96a72..86c26f1d8a8 100644
--- a/crates/ra_hir/src/code_model_api.rs
+++ b/crates/ra_hir/src/code_model_api.rs
@@ -173,7 +173,7 @@ impl Module {
 
     /// Returns a `ModuleScope`: a set of items, visible in this module.
     pub fn scope(&self, db: &impl HirDatabase) -> ModuleScope {
-        db.item_map(self.krate)[self.module_id].clone()
+        db.crate_def_map(self.krate)[self.module_id].scope.clone()
     }
 
     pub fn problems(&self, db: &impl HirDatabase) -> Vec<(TreeArc<SyntaxNode>, Problem)> {
@@ -181,8 +181,8 @@ impl Module {
     }
 
     pub fn resolver(&self, db: &impl HirDatabase) -> Resolver {
-        let item_map = db.item_map(self.krate);
-        Resolver::default().push_module_scope(item_map, *self)
+        let def_map = db.crate_def_map(self.krate);
+        Resolver::default().push_module_scope(def_map, self.module_id)
     }
 
     pub fn declarations(self, db: &impl HirDatabase) -> Vec<ModuleDef> {
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index 423922a572e..0190f49872c 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -10,7 +10,7 @@ use crate::{
     Struct, Enum, StructField,
     Const, ConstSignature, Static,
     macros::MacroExpansion,
-    nameres::{Namespace, ItemMap, lower::{LoweredModule, ImportSourceMap}, crate_def_map::{RawItems, CrateDefMap}},
+    nameres::{Namespace, lower::{LoweredModule, ImportSourceMap}, crate_def_map::{RawItems, CrateDefMap}},
     ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks, TypableDef, CallableDef, FnSig},
     adt::{StructData, EnumData},
     impl_block::{ModuleImplBlocks, ImplSourceMap},
@@ -50,9 +50,6 @@ pub trait PersistentHirDatabase: SourceDatabase + AsRef<HirInterner> {
     #[salsa::invoke(RawItems::raw_items_query)]
     fn raw_items(&self, file_id: FileId) -> Arc<RawItems>;
 
-    #[salsa::invoke(crate::nameres::ItemMap::item_map_query)]
-    fn item_map(&self, krate: Crate) -> Arc<ItemMap>;
-
     #[salsa::invoke(CrateDefMap::crate_def_map_query)]
     fn crate_def_map(&self, krate: Crate) -> Arc<CrateDefMap>;
 
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 61db4f6cc95..a188a3cc8ef 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -54,7 +54,7 @@ pub use self::{
     name::Name,
     ids::{HirFileId, MacroCallId, MacroCallLoc, HirInterner},
     macros::{MacroDef, MacroInput, MacroExpansion},
-    nameres::{ItemMap, PerNs, Namespace},
+    nameres::{PerNs, Namespace},
     ty::{Ty, Substs, display::HirDisplay},
     impl_block::{ImplBlock, ImplItem},
     docs::{Docs, Documentation},
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs
index 59297425eb3..2248842def7 100644
--- a/crates/ra_hir/src/nameres.rs
+++ b/crates/ra_hir/src/nameres.rs
@@ -17,43 +17,15 @@
 pub(crate) mod lower;
 pub(crate) mod crate_def_map;
 
-use std::{time, sync::Arc};
-
-use rustc_hash::{FxHashMap, FxHashSet};
-
-use ra_arena::map::ArenaMap;
+use rustc_hash::FxHashMap;
 use ra_db::Edition;
-use test_utils::tested_by;
 
 use crate::{
-    Module, ModuleDef,
-    Path, PathKind, PersistentHirDatabase,
-    Crate, Name,
-    nameres::{
-        crate_def_map::{CrateDefMap, ModuleId},
-        lower::{ImportId, LoweredModule, ImportData}
-    },
+    ModuleDef, Name,
+    nameres::lower::ImportId,
 };
 
-/// `ItemMap` is the result of module name resolution. It contains, for each
-/// module, the set of visible items.
-#[derive(Debug, PartialEq, Eq)]
-pub struct ItemMap {
-    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`).
-    pub(crate) prelude: Option<Module>,
-    pub(crate) extern_prelude: FxHashMap<Name, ModuleDef>,
-    per_module: ArenaMap<ModuleId, ModuleScope>,
-}
-
-impl std::ops::Index<ModuleId> for ItemMap {
-    type Output = ModuleScope;
-    fn index(&self, id: ModuleId) -> &ModuleScope {
-        &self.per_module[id]
-    }
-}
+pub(crate) use self::crate_def_map::{CrateDefMap, ModuleId};
 
 #[derive(Debug, Default, PartialEq, Eq, Clone)]
 pub struct ModuleScope {
@@ -158,292 +130,6 @@ impl<T> PerNs<T> {
     }
 }
 
-struct Resolver<'a, DB> {
-    db: &'a DB,
-    input: &'a FxHashMap<ModuleId, Arc<LoweredModule>>,
-    krate: Crate,
-    def_map: Arc<CrateDefMap>,
-    processed_imports: FxHashSet<(ModuleId, ImportId)>,
-    /// If module `a` has `use b::*`, then this contains the mapping b -> a (and the import)
-    glob_imports: FxHashMap<ModuleId, Vec<(ModuleId, ImportId)>>,
-    result: ItemMap,
-}
-
-impl<'a, DB> Resolver<'a, DB>
-where
-    DB: PersistentHirDatabase,
-{
-    fn new(
-        db: &'a DB,
-        input: &'a FxHashMap<ModuleId, Arc<LoweredModule>>,
-        krate: Crate,
-    ) -> Resolver<'a, DB> {
-        Resolver {
-            db,
-            input,
-            krate,
-            def_map: db.crate_def_map(krate),
-            processed_imports: FxHashSet::default(),
-            glob_imports: FxHashMap::default(),
-            result: ItemMap {
-                edition: krate.edition(db),
-                prelude: None,
-                extern_prelude: FxHashMap::default(),
-                per_module: ArenaMap::default(),
-            },
-        }
-    }
-
-    pub(crate) fn resolve(mut self) -> ItemMap {
-        self.populate_extern_prelude();
-        for (&module_id, items) in self.input.iter() {
-            self.populate_module(module_id, Arc::clone(items));
-        }
-
-        let mut iter = 0;
-        loop {
-            iter += 1;
-            if iter > 1000 {
-                panic!("failed to reach fixedpoint after 1000 iters")
-            }
-            let processed_imports_count = self.processed_imports.len();
-            for &module_id in self.input.keys() {
-                self.db.check_canceled();
-                self.resolve_imports(module_id);
-            }
-            if processed_imports_count == self.processed_imports.len() {
-                // no new imports resolved
-                break;
-            }
-        }
-        self.result
-    }
-
-    fn populate_extern_prelude(&mut self) {
-        for dep in self.krate.dependencies(self.db) {
-            log::debug!("crate dep {:?} -> {:?}", dep.name, dep.krate);
-            if let Some(module) = dep.krate.root_module(self.db) {
-                self.result.extern_prelude.insert(dep.name.clone(), module.into());
-            }
-            // look for the prelude
-            if self.result.prelude.is_none() {
-                let item_map = self.db.item_map(dep.krate);
-                if item_map.prelude.is_some() {
-                    self.result.prelude = item_map.prelude;
-                }
-            }
-        }
-    }
-
-    fn populate_module(&mut self, module_id: ModuleId, input: Arc<LoweredModule>) {
-        let mut module_items = ModuleScope::default();
-        for (import_id, import_data) in input.imports.iter() {
-            if let Some(last_segment) = import_data.path.segments.iter().last() {
-                if !import_data.is_glob {
-                    let name =
-                        import_data.alias.clone().unwrap_or_else(|| last_segment.name.clone());
-                    module_items
-                        .items
-                        .insert(name, Resolution { def: PerNs::none(), import: Some(import_id) });
-                }
-            }
-        }
-        // Populate explicitly declared items, except modules
-        for (name, &def) in input.declarations.iter() {
-            let resolution = Resolution { def, import: None };
-            module_items.items.insert(name.clone(), resolution);
-        }
-
-        // Populate modules
-        for (name, module_id) in self.def_map[module_id].children.iter() {
-            let module = Module { module_id: *module_id, krate: self.krate };
-            self.add_module_item(&mut module_items, name.clone(), PerNs::types(module.into()));
-        }
-
-        self.result.per_module.insert(module_id, module_items);
-    }
-
-    fn add_module_item(&self, module_items: &mut ModuleScope, name: Name, def: PerNs<ModuleDef>) {
-        let resolution = Resolution { def, import: None };
-        module_items.items.insert(name, resolution);
-    }
-
-    fn resolve_imports(&mut self, module_id: ModuleId) {
-        for (import_id, import_data) in self.input[&module_id].imports.iter() {
-            if self.processed_imports.contains(&(module_id, import_id)) {
-                // already done
-                continue;
-            }
-            if self.resolve_import(module_id, import_id, import_data) == ReachedFixedPoint::Yes {
-                log::debug!("import {:?} resolved (or definite error)", import_id);
-                self.processed_imports.insert((module_id, import_id));
-            }
-        }
-    }
-
-    fn resolve_import(
-        &mut self,
-        module_id: ModuleId,
-        import_id: ImportId,
-        import: &ImportData,
-    ) -> ReachedFixedPoint {
-        log::debug!("resolving import: {:?} ({:?})", import, self.result.edition);
-        let original_module = Module { krate: self.krate, module_id };
-
-        let (def, reached_fixedpoint) = if import.is_extern_crate {
-            let res = self.result.resolve_name_in_extern_prelude(
-                &import
-                    .path
-                    .as_ident()
-                    .expect("extern crate should have been desugared to one-element path"),
-            );
-            (res, if res.is_none() { ReachedFixedPoint::No } else { ReachedFixedPoint::Yes })
-        } else {
-            let res = self.result.resolve_path_fp(
-                self.db,
-                ResolveMode::Import,
-                original_module,
-                &import.path,
-            );
-
-            (res.resolved_def, res.reached_fixedpoint)
-        };
-
-        if reached_fixedpoint != ReachedFixedPoint::Yes {
-            return reached_fixedpoint;
-        }
-
-        if import.is_glob {
-            log::debug!("glob import: {:?}", import);
-            match def.take_types() {
-                Some(ModuleDef::Module(m)) => {
-                    if import.is_prelude {
-                        tested_by!(std_prelude);
-                        self.result.prelude = Some(m);
-                    } else if m.krate != self.krate {
-                        tested_by!(glob_across_crates);
-                        // glob import from other crate => we can just import everything once
-                        let item_map = self.db.item_map(m.krate);
-                        let scope = &item_map[m.module_id];
-                        let items = scope
-                            .items
-                            .iter()
-                            .map(|(name, res)| (name.clone(), res.clone()))
-                            .collect::<Vec<_>>();
-                        self.update(module_id, Some(import_id), &items);
-                    } else {
-                        // glob import from same crate => we do an initial
-                        // import, and then need to propagate any further
-                        // additions
-                        let scope = &self.result[m.module_id];
-                        let items = scope
-                            .items
-                            .iter()
-                            .map(|(name, res)| (name.clone(), res.clone()))
-                            .collect::<Vec<_>>();
-                        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)
-                            .or_default()
-                            .push((module_id, import_id));
-                    }
-                }
-                Some(ModuleDef::Enum(e)) => {
-                    tested_by!(glob_enum);
-                    // glob import from enum => just import all the variants
-                    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<_>>();
-                    self.update(module_id, Some(import_id), &resolutions);
-                }
-                Some(d) => {
-                    log::debug!("glob import {:?} from non-module/enum {:?}", import, d);
-                }
-                None => {
-                    log::debug!("glob import {:?} didn't resolve as type", import);
-                }
-            }
-        } else {
-            let last_segment = import.path.segments.last().unwrap();
-            let name = import.alias.clone().unwrap_or_else(|| last_segment.name.clone());
-            log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def);
-
-            // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658
-            if let Some(root_module) = self.krate.root_module(self.db) {
-                if import.is_extern_crate && module_id == root_module.module_id {
-                    if let Some(def) = def.take_types() {
-                        self.result.extern_prelude.insert(name.clone(), def);
-                    }
-                }
-            }
-            let resolution = Resolution { def, import: Some(import_id) };
-            self.update(module_id, None, &[(name, resolution)]);
-        }
-        reached_fixedpoint
-    }
-
-    fn update(
-        &mut self,
-        module_id: ModuleId,
-        import: Option<ImportId>,
-        resolutions: &[(Name, Resolution)],
-    ) {
-        self.update_recursive(module_id, import, resolutions, 0)
-    }
-
-    fn update_recursive(
-        &mut self,
-        module_id: ModuleId,
-        import: Option<ImportId>,
-        resolutions: &[(Name, Resolution)],
-        depth: usize,
-    ) {
-        if depth > 100 {
-            // prevent stack overflows (but this shouldn't be possible)
-            panic!("infinite recursion in glob imports!");
-        }
-        let module_items = self.result.per_module.get_mut(module_id).unwrap();
-        let mut changed = false;
-        for (name, res) in resolutions {
-            let existing = module_items.items.entry(name.clone()).or_default();
-            if existing.def.types.is_none() && res.def.types.is_some() {
-                existing.def.types = res.def.types;
-                existing.import = import.or(res.import);
-                changed = true;
-            }
-            if existing.def.values.is_none() && res.def.values.is_some() {
-                existing.def.values = res.def.values;
-                existing.import = import.or(res.import);
-                changed = true;
-            }
-        }
-        if !changed {
-            return;
-        }
-        let glob_imports = self
-            .glob_imports
-            .get(&module_id)
-            .into_iter()
-            .flat_map(|v| v.iter())
-            .cloned()
-            .collect::<Vec<_>>();
-        for (glob_importing_module, glob_import) in glob_imports {
-            // We pass the glob import so that the tracked import in those modules is that glob import
-            self.update_recursive(glob_importing_module, Some(glob_import), resolutions, depth + 1);
-        }
-    }
-}
-
 #[derive(Debug, Clone)]
 struct ResolvePathResult {
     resolved_def: PerNs<ModuleDef>,
@@ -476,220 +162,3 @@ enum ReachedFixedPoint {
     Yes,
     No,
 }
-
-impl ItemMap {
-    pub(crate) fn item_map_query(db: &impl PersistentHirDatabase, krate: Crate) -> Arc<ItemMap> {
-        let start = time::Instant::now();
-        let def_map = db.crate_def_map(krate);
-        let input = def_map
-            .modules()
-            .map(|module_id| (module_id, db.lower_module(Module { krate, module_id })))
-            .collect::<FxHashMap<_, _>>();
-
-        let resolver = Resolver::new(db, &input, krate);
-        let res = resolver.resolve();
-        let elapsed = start.elapsed();
-        log::info!("item_map: {:?}", elapsed);
-        Arc::new(res)
-    }
-
-    pub(crate) fn resolve_path(
-        &self,
-        db: &impl PersistentHirDatabase,
-        original_module: Module,
-        path: &Path,
-    ) -> (PerNs<ModuleDef>, Option<usize>) {
-        let res = self.resolve_path_fp(db, ResolveMode::Other, original_module, path);
-        (res.resolved_def, res.segment_index)
-    }
-
-    fn resolve_in_prelude(
-        &self,
-        db: &impl PersistentHirDatabase,
-        original_module: Module,
-        name: &Name,
-    ) -> PerNs<ModuleDef> {
-        if let Some(prelude) = self.prelude {
-            let resolution = if prelude.krate == original_module.krate {
-                self[prelude.module_id].items.get(name).cloned()
-            } else {
-                db.item_map(prelude.krate)[prelude.module_id].items.get(name).cloned()
-            };
-            resolution.map(|r| r.def).unwrap_or_else(PerNs::none)
-        } else {
-            PerNs::none()
-        }
-    }
-
-    pub(crate) fn resolve_name_in_module(
-        &self,
-        db: &impl PersistentHirDatabase,
-        module: Module,
-        name: &Name,
-    ) -> PerNs<ModuleDef> {
-        // Resolve in:
-        //  - current module / scope
-        //  - extern prelude
-        //  - std prelude
-        let from_scope = self[module.module_id].items.get(name).map_or(PerNs::none(), |it| it.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, module, name);
-
-        from_scope.or(from_extern_prelude).or(from_prelude)
-    }
-
-    fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs<ModuleDef> {
-        self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it))
-    }
-
-    fn resolve_name_in_crate_root_or_extern_prelude(
-        &self,
-        db: &impl PersistentHirDatabase,
-        module: Module,
-        name: &Name,
-    ) -> PerNs<ModuleDef> {
-        let crate_root = module.crate_root(db);
-        let from_crate_root =
-            self[crate_root.module_id].items.get(name).map_or(PerNs::none(), |it| it.def);
-        let from_extern_prelude = self.resolve_name_in_extern_prelude(name);
-
-        from_crate_root.or(from_extern_prelude)
-    }
-
-    // Returns Yes if we are sure that additions to `ItemMap` wouldn't change
-    // the result.
-    fn resolve_path_fp(
-        &self,
-        db: &impl PersistentHirDatabase,
-        mode: ResolveMode,
-        original_module: Module,
-        path: &Path,
-    ) -> ResolvePathResult {
-        let mut segments = path.segments.iter().enumerate();
-        let mut curr_per_ns: PerNs<ModuleDef> = match path.kind {
-            PathKind::Crate => PerNs::types(original_module.crate_root(db).into()),
-            PathKind::Self_ => PerNs::types(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)
-            // TODO 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(
-                    db,
-                    original_module,
-                    &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) = original_module.parent(db) {
-                    PerNs::types(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
-                }
-            }
-        };
-
-        for (i, segment) in segments {
-            let curr = match curr_per_ns.as_ref().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 != original_module.krate {
-                        let path = Path {
-                            segments: path.segments[i..].iter().cloned().collect(),
-                            kind: PathKind::Self_,
-                        };
-                        log::debug!("resolving {:?} in other crate", path);
-                        let item_map = db.item_map(module.krate);
-                        let (def, s) = item_map.resolve_path(db, *module, &path);
-                        return ResolvePathResult::with(
-                            def,
-                            ReachedFixedPoint::Yes,
-                            s.map(|s| s + i),
-                        );
-                    }
-
-                    match self[module.module_id].items.get(&segment.name) {
-                        Some(res) if !res.def.is_none() => res.def,
-                        _ => {
-                            log::debug!("path segment {:?} not found", segment.name);
-                            return ResolvePathResult::empty(ReachedFixedPoint::No);
-                        }
-                    }
-                }
-                ModuleDef::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).into()),
-                        ReachedFixedPoint::Yes,
-                        Some(i),
-                    );
-                }
-            };
-        }
-        ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None)
-    }
-}
diff --git a/crates/ra_hir/src/nameres/crate_def_map.rs b/crates/ra_hir/src/nameres/crate_def_map.rs
index 37b36719f02..cc495505356 100644
--- a/crates/ra_hir/src/nameres/crate_def_map.rs
+++ b/crates/ra_hir/src/nameres/crate_def_map.rs
@@ -149,8 +149,16 @@ impl CrateDefMap {
         &self.problems
     }
 
-    pub(crate) fn modules<'a>(&'a self) -> impl Iterator<Item = ModuleId> + 'a {
-        self.modules.iter().map(|(id, _data)| id)
+    pub(crate) fn mk_module(&self, module_id: ModuleId) -> Module {
+        Module { krate: self.krate, module_id }
+    }
+
+    pub(crate) fn prelude(&self) -> Option<Module> {
+        self.prelude
+    }
+
+    pub(crate) fn extern_prelude(&self) -> &FxHashMap<Name, ModuleDef> {
+        &self.extern_prelude
     }
 
     pub(crate) fn find_module_by_source(
@@ -169,6 +177,16 @@ impl CrateDefMap {
         Some(module_id)
     }
 
+    pub(crate) fn resolve_path(
+        &self,
+        db: &impl PersistentHirDatabase,
+        original_module: ModuleId,
+        path: &Path,
+    ) -> (PerNs<ModuleDef>, Option<usize>) {
+        let res = self.resolve_path_fp(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(
@@ -254,8 +272,8 @@ impl CrateDefMap {
                             kind: PathKind::Self_,
                         };
                         log::debug!("resolving {:?} in other crate", path);
-                        let item_map = db.item_map(module.krate);
-                        let (def, s) = item_map.resolve_path(db, *module, &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,
@@ -313,7 +331,7 @@ impl CrateDefMap {
         from_crate_root.or(from_extern_prelude)
     }
 
-    fn resolve_name_in_module(
+    pub(crate) fn resolve_name_in_module(
         &self,
         db: &impl PersistentHirDatabase,
         module: ModuleId,
@@ -340,7 +358,7 @@ impl CrateDefMap {
             let resolution = if prelude.krate == self.krate {
                 self[prelude.module_id].scope.items.get(name).cloned()
             } else {
-                db.item_map(prelude.krate)[prelude.module_id].items.get(name).cloned()
+                db.crate_def_map(prelude.krate)[prelude.module_id].scope.items.get(name).cloned()
             };
             resolution.map(|r| r.def).unwrap_or_else(PerNs::none)
         } else {
diff --git a/crates/ra_hir/src/nameres/crate_def_map/collector.rs b/crates/ra_hir/src/nameres/crate_def_map/collector.rs
index 68f74b8661c..8b727e2c93a 100644
--- a/crates/ra_hir/src/nameres/crate_def_map/collector.rs
+++ b/crates/ra_hir/src/nameres/crate_def_map/collector.rs
@@ -26,9 +26,9 @@ pub(super) fn collect_defs(
         }
         // look for the prelude
         if def_map.prelude.is_none() {
-            let item_map = db.item_map(dep.krate);
-            if item_map.prelude.is_some() {
-                def_map.prelude = item_map.prelude;
+            let map = db.crate_def_map(dep.krate);
+            if map.prelude.is_some() {
+                def_map.prelude = map.prelude;
             }
         }
     }
@@ -162,8 +162,8 @@ where
                     } 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.item_map(m.krate);
-                        let scope = &item_map[m.module_id];
+                        let item_map = self.db.crate_def_map(m.krate);
+                        let scope = &item_map[m.module_id].scope;
                         let items = scope
                             .items
                             .iter()
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs
index 57e7d0b9ad0..e85447eeb37 100644
--- a/crates/ra_hir/src/resolve.rs
+++ b/crates/ra_hir/src/resolve.rs
@@ -4,10 +4,10 @@ use std::sync::Arc;
 use rustc_hash::FxHashMap;
 
 use crate::{
-    ModuleDef, Module,
+    ModuleDef,
     db::HirDatabase,
     name::{Name, KnownName},
-    nameres::{PerNs, ItemMap},
+    nameres::{PerNs, CrateDefMap, ModuleId},
     generics::GenericParams,
     expr::{scope::{ExprScopes, ScopeId}, PatId, Body},
     impl_block::ImplBlock,
@@ -22,8 +22,8 @@ pub struct Resolver {
 // TODO how to store these best
 #[derive(Debug, Clone)]
 pub(crate) struct ModuleItemMap {
-    item_map: Arc<ItemMap>,
-    module: Module,
+    crate_def_map: Arc<CrateDefMap>,
+    module_id: ModuleId,
 }
 
 #[derive(Debug, Clone)]
@@ -175,9 +175,9 @@ impl Resolver {
         names
     }
 
-    fn module(&self) -> Option<(&ItemMap, Module)> {
+    fn module(&self) -> Option<(&CrateDefMap, ModuleId)> {
         self.scopes.iter().rev().find_map(|scope| match scope {
-            Scope::ModuleScope(m) => Some((&*m.item_map, m.module.clone())),
+            Scope::ModuleScope(m) => Some((&*m.crate_def_map, m.module_id)),
 
             _ => None,
         })
@@ -206,8 +206,12 @@ impl Resolver {
         self.push_scope(Scope::ImplBlockScope(impl_block))
     }
 
-    pub(crate) fn push_module_scope(self, item_map: Arc<ItemMap>, module: Module) -> Resolver {
-        self.push_scope(Scope::ModuleScope(ModuleItemMap { item_map, module }))
+    pub(crate) fn push_module_scope(
+        self,
+        crate_def_map: Arc<CrateDefMap>,
+        module_id: ModuleId,
+    ) -> Resolver {
+        self.push_scope(Scope::ModuleScope(ModuleItemMap { crate_def_map, module_id }))
     }
 
     pub(crate) fn push_expr_scope(
@@ -224,9 +228,11 @@ impl Scope {
         match self {
             Scope::ModuleScope(m) => {
                 if let Some(KnownName::SelfParam) = name.as_known_name() {
-                    PerNs::types(Resolution::Def(m.module.into()))
+                    PerNs::types(Resolution::Def(m.crate_def_map.mk_module(m.module_id).into()))
                 } else {
-                    m.item_map.resolve_name_in_module(db, m.module, name).map(Resolution::Def)
+                    m.crate_def_map
+                        .resolve_name_in_module(db, m.module_id, name)
+                        .map(Resolution::Def)
                 }
             }
             Scope::GenericParams(gp) => match gp.find_by_name(name) {
@@ -261,15 +267,15 @@ impl Scope {
                 //         def: m.module.into(),
                 //     }),
                 // );
-                m.item_map[m.module.module_id].entries().for_each(|(name, res)| {
+                m.crate_def_map[m.module_id].scope.entries().for_each(|(name, res)| {
                     f(name.clone(), res.def.map(Resolution::Def));
                 });
-                m.item_map.extern_prelude.iter().for_each(|(name, def)| {
+                m.crate_def_map.extern_prelude().iter().for_each(|(name, def)| {
                     f(name.clone(), PerNs::types(Resolution::Def(*def)));
                 });
-                if let Some(prelude) = m.item_map.prelude {
-                    let prelude_item_map = db.item_map(prelude.krate);
-                    prelude_item_map[prelude.module_id].entries().for_each(|(name, res)| {
+                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.map(Resolution::Def));
                     });
                 }