Repository: rust-analyzer/rust-analyzer
Pull request #2624 (2019-12-20 19:50:47)

Separate module item from module scope
bors r+


Patch:
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index ecf883272d..fca3a29509 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -221,7 +221,7 @@ impl Module {
 
     pub fn impl_blocks(self, db: &impl DefDatabase) -> Vec<ImplBlock> {
         let def_map = db.crate_def_map(self.id.krate);
-        def_map[self.id.local_id].impls.iter().copied().map(ImplBlock::from).collect()
+        def_map[self.id.local_id].scope.impls().map(ImplBlock::from).collect()
     }
 
     pub(crate) fn with_module_id(self, module_id: LocalModuleId) -> Module {
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index a92c01f86f..d9ce6bcff6 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -17,13 +17,14 @@ use rustc_hash::FxHashMap;
 use crate::{
     db::DefDatabase,
     expr::{Expr, ExprId, Pat, PatId},
-    nameres::{BuiltinShadowMode, CrateDefMap},
+    item_scope::BuiltinShadowMode,
+    nameres::CrateDefMap,
     path::{ModPath, Path},
     src::HasSource,
     DefWithBodyId, HasModule, Lookup, ModuleDefId, ModuleId,
 };
 
-pub(crate) struct Expander {
+struct Expander {
     crate_def_map: Arc<CrateDefMap>,
     current_file_id: HirFileId,
     hygiene: Hygiene,
@@ -32,22 +33,18 @@ pub(crate) struct Expander {
 }
 
 impl Expander {
-    pub(crate) fn new(
-        db: &impl DefDatabase,
-        current_file_id: HirFileId,
-        module: ModuleId,
-    ) -> Expander {
+    fn new(db: &impl DefDatabase, current_file_id: HirFileId, module: ModuleId) -> Expander {
         let crate_def_map = db.crate_def_map(module.krate);
         let hygiene = Hygiene::new(db, current_file_id);
         let ast_id_map = db.ast_id_map(current_file_id);
         Expander { crate_def_map, current_file_id, hygiene, ast_id_map, module }
     }
 
-    pub(crate) fn enter_expand<T: ast::AstNode, DB: DefDatabase>(
+    fn enter_expand(
         &mut self,
-        db: &DB,
+        db: &impl DefDatabase,
         macro_call: ast::MacroCall,
-    ) -> Option<(Mark, T)> {
+    ) -> Option<(Mark, ast::Expr)> {
         let ast_id = AstId::new(
             self.current_file_id,
             db.ast_id_map(self.current_file_id).ast_id(&macro_call),
@@ -58,7 +55,7 @@ impl Expander {
                 let call_id = def.as_call_id(db, MacroCallKind::FnLike(ast_id));
                 let file_id = call_id.as_file();
                 if let Some(node) = db.parse_or_expand(file_id) {
-                    if let Some(expr) = T::cast(node) {
+                    if let Some(expr) = ast::Expr::cast(node) {
                         log::debug!("macro expansion {:#?}", expr.syntax());
 
                         let mark = Mark {
@@ -81,14 +78,14 @@ impl Expander {
         None
     }
 
-    pub(crate) fn exit(&mut self, db: &impl DefDatabase, mut mark: Mark) {
+    fn exit(&mut self, db: &impl DefDatabase, mut mark: Mark) {
         self.hygiene = Hygiene::new(db, mark.file_id);
         self.current_file_id = mark.file_id;
         self.ast_id_map = mem::take(&mut mark.ast_id_map);
         mark.bomb.defuse();
     }
 
-    pub(crate) fn to_source<T>(&self, value: T) -> InFile<T> {
+    fn to_source<T>(&self, value: T) -> InFile<T> {
         InFile { file_id: self.current_file_id, value }
     }
 
@@ -113,7 +110,7 @@ impl Expander {
     }
 }
 
-pub(crate) struct Mark {
+struct Mark {
     file_id: HirFileId,
     ast_id_map: Arc<AstIdMap>,
     bomb: DropBomb,
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index be5d17d85e..853e17bae7 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -372,9 +372,8 @@ where
                         arg_types.push(type_ref);
                     }
                 }
-                let ret_type = e.ret_type().and_then(|r| r.type_ref()).map(TypeRef::from_ast);
                 let body = self.collect_expr_opt(e.body());
-                self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr)
+                self.alloc_expr(Expr::Lambda { args, arg_types, body }, syntax_ptr)
             }
             ast::Expr::BinExpr(e) => {
                 let lhs = self.collect_expr_opt(e.lhs());
diff --git a/crates/ra_hir_def/src/child_by_source.rs b/crates/ra_hir_def/src/child_by_source.rs
index f5a65ad409..4488e85020 100644
--- a/crates/ra_hir_def/src/child_by_source.rs
+++ b/crates/ra_hir_def/src/child_by_source.rs
@@ -80,9 +80,9 @@ impl ChildBySource for ModuleId {
 
         module_data.scope.declarations().for_each(|item| add_module_def(db, &mut res, item));
 
-        for &impl_ in module_data.impls.iter() {
-            let src = impl_.lookup(db).source(db);
-            res[keys::IMPL].insert(src, impl_)
+        for imp in module_data.scope.impls() {
+            let src = imp.lookup(db).source(db);
+            res[keys::IMPL].insert(src, imp)
         }
 
         res
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs
index b0a3f17845..14e86936bc 100644
--- a/crates/ra_hir_def/src/data.rs
+++ b/crates/ra_hir_def/src/data.rs
@@ -4,16 +4,16 @@ use std::sync::Arc;
 
 use hir_expand::{
     name::{name, AsName, Name},
-    AstId, InFile,
+    AstId,
 };
-use ra_syntax::ast::{self, AstNode, ImplItem, ModuleItemOwner, NameOwner, TypeAscriptionOwner};
+use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner};
 
 use crate::{
     db::DefDatabase,
     src::HasSource,
     type_ref::{Mutability, TypeRef},
-    AssocContainerId, AssocItemId, ConstId, ConstLoc, Expander, FunctionId, FunctionLoc, HasModule,
-    ImplId, Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc,
+    AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, ImplId, Intern,
+    Lookup, StaticId, TraitId, TypeAliasId, TypeAliasLoc,
 };
 
 #[derive(Debug, Clone, PartialEq, Eq)]
@@ -167,24 +167,46 @@ pub struct ImplData {
 
 impl ImplData {
     pub(crate) fn impl_data_query(db: &impl DefDatabase, id: ImplId) -> Arc<ImplData> {
-        let impl_loc = id.lookup(db);
-        let src = impl_loc.source(db);
+        let src = id.lookup(db).source(db);
+        let items = db.ast_id_map(src.file_id);
 
         let target_trait = src.value.target_trait().map(TypeRef::from_ast);
         let target_type = TypeRef::from_ast_opt(src.value.target_type());
         let is_negative = src.value.is_negative();
-        let module_id = impl_loc.container.module(db);
 
-        let mut items = Vec::new();
-        if let Some(item_list) = src.value.item_list() {
-            items.extend(collect_impl_items(db, item_list.impl_items(), src.file_id, id));
-            items.extend(collect_impl_items_in_macros(
-                db,
-                module_id,
-                &src.with_value(item_list),
-                id,
-            ));
-        }
+        let items = if let Some(item_list) = src.value.item_list() {
+            item_list
+                .impl_items()
+                .map(|item_node| match item_node {
+                    ast::ImplItem::FnDef(it) => {
+                        let def = FunctionLoc {
+                            container: AssocContainerId::ImplId(id),
+                            ast_id: AstId::new(src.file_id, items.ast_id(&it)),
+                        }
+                        .intern(db);
+                        def.into()
+                    }
+                    ast::ImplItem::ConstDef(it) => {
+                        let def = ConstLoc {
+                            container: AssocContainerId::ImplId(id),
+                            ast_id: AstId::new(src.file_id, items.ast_id(&it)),
+                        }
+                        .intern(db);
+                        def.into()
+                    }
+                    ast::ImplItem::TypeAliasDef(it) => {
+                        let def = TypeAliasLoc {
+                            container: AssocContainerId::ImplId(id),
+                            ast_id: AstId::new(src.file_id, items.ast_id(&it)),
+                        }
+                        .intern(db);
+                        def.into()
+                    }
+                })
+                .collect()
+        } else {
+            Vec::new()
+        };
 
         let res = ImplData { target_trait, target_type, items, is_negative };
         Arc::new(res)
@@ -215,66 +237,3 @@ impl ConstData {
         ConstData { name, type_ref }
     }
 }
-
-fn collect_impl_items_in_macros(
-    db: &impl DefDatabase,
-    module_id: ModuleId,
-    impl_block: &InFile<ast::ItemList>,
-    id: ImplId,
-) -> Vec<AssocItemId> {
-    let mut expander = Expander::new(db, impl_block.file_id, module_id);
-    let mut res = Vec::new();
-
-    for m in impl_block.value.syntax().children().filter_map(ast::MacroCall::cast) {
-        if let Some((mark, items)) = expander.enter_expand(db, m) {
-            let items: InFile<ast::MacroItems> = expander.to_source(items);
-            expander.exit(db, mark);
-            res.extend(collect_impl_items(
-                db,
-                items.value.items().filter_map(|it| ImplItem::cast(it.syntax().clone())),
-                items.file_id,
-                id,
-            ));
-        }
-    }
-
-    res
-}
-
-fn collect_impl_items(
-    db: &impl DefDatabase,
-    impl_items: impl Iterator<Item = ImplItem>,
-    file_id: crate::HirFileId,
-    id: ImplId,
-) -> Vec<AssocItemId> {
-    let items = db.ast_id_map(file_id);
-
-    impl_items
-        .map(|item_node| match item_node {
-            ast::ImplItem::FnDef(it) => {
-                let def = FunctionLoc {
-                    container: AssocContainerId::ImplId(id),
-                    ast_id: AstId::new(file_id, items.ast_id(&it)),
-                }
-                .intern(db);
-                def.into()
-            }
-            ast::ImplItem::ConstDef(it) => {
-                let def = ConstLoc {
-                    container: AssocContainerId::ImplId(id),
-                    ast_id: AstId::new(file_id, items.ast_id(&it)),
-                }
-                .intern(db);
-                def.into()
-            }
-            ast::ImplItem::TypeAliasDef(it) => {
-                let def = TypeAliasLoc {
-                    container: AssocContainerId::ImplId(id),
-                    ast_id: AstId::new(file_id, items.ast_id(&it)),
-                }
-                .intern(db);
-                def.into()
-            }
-        })
-        .collect()
-}
diff --git a/crates/ra_hir_def/src/expr.rs b/crates/ra_hir_def/src/expr.rs
index a75ef9970d..6fad80a8d4 100644
--- a/crates/ra_hir_def/src/expr.rs
+++ b/crates/ra_hir_def/src/expr.rs
@@ -143,7 +143,6 @@ pub enum Expr {
     Lambda {
         args: Vec<PatId>,
         arg_types: Vec<Option<TypeRef>>,
-        ret_type: Option<TypeRef>,
         body: ExprId,
     },
     Tuple {
diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs
new file mode 100644
index 0000000000..6b9be8325d
--- /dev/null
+++ b/crates/ra_hir_def/src/item_scope.rs
@@ -0,0 +1,165 @@
+//! Describes items defined or visible (ie, imported) in a certain scope.
+//! This is shared between modules and blocks.
+
+use hir_expand::name::Name;
+use once_cell::sync::Lazy;
+use rustc_hash::FxHashMap;
+
+use crate::{per_ns::PerNs, BuiltinType, ImplId, LocalImportId, MacroDefId, ModuleDefId, TraitId};
+
+#[derive(Debug, Default, PartialEq, Eq)]
+pub struct ItemScope {
+    items: FxHashMap<Name, Resolution>,
+    impls: Vec<ImplId>,
+    /// Macros visible in current module in legacy textual scope
+    ///
+    /// For macros invoked by an unqualified 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 qualified 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()
+});
+
+/// Shadow mode for builtin type which can be shadowed by module.
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+pub(crate) enum BuiltinShadowMode {
+    // Prefer Module
+    Module,
+    // Prefer Other Types
+    Other,
+}
+
+/// 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 ItemScope {
+    pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a Name, &'a Resolution)> + 'a {
+        //FIXME: shadowing
+        self.items.iter().chain(BUILTIN_SCOPE.iter())
+    }
+
+    pub fn declarations(&self) -> impl Iterator<Item = ModuleDefId> + '_ {
+        self.entries()
+            .filter_map(|(_name, res)| if res.import.is_none() { Some(res.def) } else { None })
+            .flat_map(|per_ns| {
+                per_ns.take_types().into_iter().chain(per_ns.take_values().into_iter())
+            })
+    }
+
+    pub fn impls(&self) -> impl Iterator<Item = ImplId> + ExactSizeIterator + '_ {
+        self.impls.iter().copied()
+    }
+
+    /// Iterate over all module scoped macros
+    pub(crate) fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a {
+        self.items
+            .iter()
+            .filter_map(|(name, res)| res.def.take_macros().map(|macro_| (name, macro_)))
+    }
+
+    /// Iterate over all legacy textual scoped macros visible at the end of the module
+    pub(crate) 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(crate) fn get(&self, name: &Name, shadow: BuiltinShadowMode) -> Option<&Resolution> {
+        match shadow {
+            BuiltinShadowMode::Module => self.items.get(name).or_else(|| BUILTIN_SCOPE.get(name)),
+            BuiltinShadowMode::Other => {
+                let item = self.items.get(name);
+                if let Some(res) = item {
+                    if let Some(ModuleDefId::ModuleId(_)) = res.def.take_types() {
+                        return BUILTIN_SCOPE.get(name).or(item);
+                    }
+                }
+
+                item.or_else(|| BUILTIN_SCOPE.get(name))
+            }
+        }
+    }
+
+    pub(crate) 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,
+        })
+    }
+
+    pub(crate) fn get_legacy_macro(&self, name: &Name) -> Option<MacroDefId> {
+        self.legacy_macros.get(name).copied()
+    }
+
+    pub(crate) fn define_impl(&mut self, imp: ImplId) {
+        self.impls.push(imp)
+    }
+
+    pub(crate) fn define_legacy_macro(&mut self, name: Name, mac: MacroDefId) {
+        self.legacy_macros.insert(name, mac);
+    }
+
+    pub(crate) fn push_res(
+        &mut self,
+        name: Name,
+        res: &Resolution,
+        import: Option<LocalImportId>,
+    ) -> bool {
+        let mut changed = false;
+        let existing = self.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 existing.def.macros.is_none() && res.def.macros.is_some() {
+            existing.def.macros = res.def.macros;
+            existing.import = import.or(res.import);
+            changed = true;
+        }
+
+        if existing.def.is_none()
+            && res.def.is_none()
+            && existing.import.is_none()
+            && res.import.is_some()
+        {
+            existing.import = res.import;
+        }
+        changed
+    }
+
+    pub(crate) fn collect_resolutions(&self) -> Vec<(Name, Resolution)> {
+        self.items.iter().map(|(name, res)| (name.clone(), res.clone())).collect()
+    }
+
+    pub(crate) fn collect_legacy_macros(&self) -> FxHashMap<Name, MacroDefId> {
+        self.legacy_macros.clone()
+    }
+}
+
+#[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<LocalImportId>,
+}
diff --git a/crates/ra_hir_def/src/lang_item.rs b/crates/ra_hir_def/src/lang_item.rs
index f4fdbdcfc7..cef061837b 100644
--- a/crates/ra_hir_def/src/lang_item.rs
+++ b/crates/ra_hir_def/src/lang_item.rs
@@ -81,7 +81,7 @@ impl LangItems {
         // Look for impl targets
         let def_map = db.crate_def_map(module.krate);
         let module_data = &def_map[module.local_id];
-        for &impl_block in module_data.impls.iter() {
+        for impl_block in module_data.scope.impls() {
             self.collect_lang_item(db, impl_block, LangItemTarget::ImplBlockId)
         }
 
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs
index 6bb5408a86..bf8d6d1d46 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -15,6 +15,7 @@ pub mod type_ref;
 pub mod builtin_type;
 pub mod diagnostics;
 pub mod per_ns;
+pub mod item_scope;
 
 pub mod dyn_map;
 pub mod keys;
@@ -47,7 +48,6 @@ use ra_arena::{impl_arena_id, RawId};
 use ra_db::{impl_intern_key, salsa, CrateId};
 use ra_syntax::{ast, AstNode};
 
-use crate::body::Expander;
 use crate::builtin_type::BuiltinType;
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs
index af52fa36ee..5d4ca73a39 100644
--- a/crates/ra_hir_def/src/nameres.rs
+++ b/crates/ra_hir_def/src/nameres.rs
@@ -57,8 +57,7 @@ mod tests;
 
 use std::sync::Arc;
 
-use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile, MacroDefId};
-use once_cell::sync::Lazy;
+use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile};
 use ra_arena::Arena;
 use ra_db::{CrateId, Edition, FileId, FilePosition};
 use ra_prof::profile;
@@ -69,12 +68,12 @@ use ra_syntax::{
 use rustc_hash::FxHashMap;
 
 use crate::{
-    builtin_type::BuiltinType,
     db::DefDatabase,
+    item_scope::{BuiltinShadowMode, ItemScope},
     nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode},
     path::ModPath,
     per_ns::PerNs,
-    AstId, ImplId, LocalImportId, LocalModuleId, ModuleDefId, ModuleId, TraitId,
+    AstId, LocalModuleId, ModuleDefId, ModuleId,
 };
 
 /// Contains all top-level defs from a macro-expanded crate
@@ -166,113 +165,10 @@ impl ModuleOrigin {
 pub struct ModuleData {
     pub parent: Option<LocalModuleId>,
     pub children: FxHashMap<Name, LocalModuleId>,
-    pub scope: ModuleScope,
+    pub scope: ItemScope,
 
     /// Where does this module come from?
     pub origin: ModuleOrigin,
-
-    pub impls: Vec<ImplId>,
-}
-
-#[derive(Debug, Default, PartialEq, Eq)]
-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, 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()
-});
-
-/// Shadow mode for builtin type which can be shadowed by module.
-#[derive(Debug, Copy, Clone, PartialEq, Eq)]
-pub enum BuiltinShadowMode {
-    // Prefer Module
-    Module,
-    // Prefer Other Types
-    Other,
-}
-
-/// 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())
-    }
-
-    pub fn declarations(&self) -> impl Iterator<Item = ModuleDefId> + '_ {
-        self.entries()
-            .filter_map(|(_name, res)| if res.import.is_none() { Some(res.def) } else { None })
-            .flat_map(|per_ns| {
-                per_ns.take_types().into_iter().chain(per_ns.take_values().into_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.take_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, shadow: BuiltinShadowMode) -> Option<&Resolution> {
-        match shadow {
-            BuiltinShadowMode::Module => self.items.get(name).or_else(|| BUILTIN_SCOPE.get(name)),
-            BuiltinShadowMode::Other => {
-                let item = self.items.get(name);
-                if let Some(res) = item {
-                    if let Some(ModuleDefId::ModuleId(_)) = res.def.take_types() {
-                        return BUILTIN_SCOPE.get(name).or(item);
-                    }
-                }
-
-                item.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<LocalImportId>,
 }
 
 impl CrateDefMap {
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index e68bf48688..8b641d8b56 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -18,9 +18,10 @@ use test_utils::tested_by;
 use crate::{
     attr::Attrs,
     db::DefDatabase,
+    item_scope::Resolution,
     nameres::{
         diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint,
-        raw, BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, Resolution, ResolveMode,
+        raw, BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, ResolveMode,
     },
     path::{ModPath, PathKind},
     per_ns::PerNs,
@@ -225,14 +226,14 @@ where
 
     /// Define a legacy textual scoped macro in module
     ///
-    /// We use a map `legacy_macros` to store all legacy textual scoped macros visable per module.
+    /// We use a map `legacy_macros` to store all legacy textual scoped macros visible per module.
     /// It will clone all macros from parent legacy scope, whose definition is prior to
     /// the definition of current module.
-    /// And also, `macro_use` on a module will import all legacy macros visable inside to
+    /// And also, `macro_use` on a module will import all legacy macros visible inside to
     /// current legacy scope, with possible shadowing.
-    fn define_legacy_macro(&mut self, module_id: LocalModuleId, name: Name, macro_: MacroDefId) {
+    fn define_legacy_macro(&mut self, module_id: LocalModuleId, name: Name, mac: MacroDefId) {
         // Always shadowing
-        self.def_map.modules[module_id].scope.legacy_macros.insert(name, macro_);
+        self.def_map.modules[module_id].scope.define_legacy_macro(name, mac);
     }
 
     /// Import macros from `#[macro_use] extern crate`.
@@ -371,11 +372,7 @@ where
                         let scope = &item_map[m.local_id].scope;
 
                         // Module scoped macros is included
-                        let items = scope
-                            .items
-                            .iter()
-                            .map(|(name, res)| (name.clone(), res.clone()))
-                            .collect::<Vec<_>>();
+                        let items = scope.collect_resolutions();
 
                         self.update(module_id, Some(import_id), &items);
                     } else {
@@ -385,11 +382,7 @@ where
                         let scope = &self.def_map[m.local_id].scope;
 
                         // Module scoped macros is included
-                        let items = scope
-                            .items
-                            .iter()
-                            .map(|(name, res)| (name.clone(), res.clone()))
-                            .collect::<Vec<_>>();
+                        let items = scope.collect_resolutions();
 
                         self.update(module_id, Some(import_id), &items);
                         // record the glob import in case we add further items
@@ -466,34 +459,10 @@ where
             // prevent stack overflows (but this shouldn't be possible)
             panic!("infinite recursion in glob imports!");
         }
-        let module_items = &mut self.def_map.modules[module_id].scope;
+        let scope = &mut self.def_map.modules[module_id].scope;
         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 existing.def.macros.is_none() && res.def.macros.is_some() {
-                existing.def.macros = res.def.macros;
-                existing.import = import.or(res.import);
-                changed = true;
-            }
-
-            if existing.def.is_none()
-                && res.def.is_none()
-                && existing.import.is_none()
-                && res.import.is_some()
-            {
-                existing.import = res.import;
-            }
+            changed |= scope.push_res(name.clone(), res, import);
         }
 
         if !changed {
@@ -666,7 +635,9 @@ where
                         let impl_id =
                             ImplLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
                                 .intern(self.def_collector.db);
-                        self.def_collector.def_map.modules[self.module_id].impls.push(impl_id)
+                        self.def_collector.def_map.modules[self.module_id]
+                            .scope
+                            .define_impl(impl_id)
                     }
                 }
             }
@@ -740,7 +711,9 @@ where
         let res = modules.alloc(ModuleData::default());
         modules[res].parent = Some(self.module_id);
         modules[res].origin = ModuleOrigin::not_sure_file(definition, declaration);
-        modules[res].scope.legacy_macros = modules[self.module_id].scope.legacy_macros.clone();
+        for (name, mac) in modules[self.module_id].scope.collect_legacy_macros() {
+            modules[res].scope.define_legacy_macro(name, mac)
+        }
         modules[self.module_id].children.insert(name.clone(), res);
         let resolution = Resolution {
             def: PerNs::types(
@@ -904,7 +877,7 @@ where
     }
 
     fn import_all_legacy_macros(&mut self, module_id: LocalModuleId) {
-        let macros = self.def_collector.def_map[module_id].scope.legacy_macros.clone();
+        let macros = self.def_collector.def_map[module_id].scope.collect_legacy_macros();
         for (name, macro_) in macros {
             self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_);
         }
diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs
index 8e12942011..00325cd99a 100644
--- a/crates/ra_hir_def/src/path.rs
+++ b/crates/ra_hir_def/src/path.rs
@@ -135,7 +135,7 @@ impl Path {
     }
 
     pub fn type_anchor(&self) -> Option<&TypeRef> {
-        self.type_anchor.as_deref()
+        self.type_anchor.as_ref().map(|it| &**it)
     }
 
     pub fn segments(&self) -> PathSegments<'_> {
diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs
index af9d194f8a..83013fed3d 100644
--- a/crates/ra_hir_def/src/resolver.rs
+++ b/crates/ra_hir_def/src/resolver.rs
@@ -14,7 +14,8 @@ use crate::{
     db::DefDatabase,
     expr::{ExprId, PatId},
     generics::GenericParams,
-    nameres::{BuiltinShadowMode, CrateDefMap},
+    item_scope::BuiltinShadowMode,
+    nameres::CrateDefMap,
     path::{ModPath, PathKind},
     per_ns::PerNs,
     AdtId, AssocContainerId, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId,
diff --git a/crates/ra_hir_expand/src/db.rs b/crates/ra_hir_expand/src/db.rs
index d86445abff..f68aca7898 100644
--- a/crates/ra_hir_expand/src/db.rs
+++ b/crates/ra_hir_expand/src/db.rs
@@ -188,7 +188,6 @@ fn to_fragment_kind(db: &dyn AstDatabase, macro_call_id: MacroCallId) -> Fragmen
         ARG_LIST => FragmentKind::Expr,
         TRY_EXPR => FragmentKind::Expr,
         TUPLE_EXPR => FragmentKind::Expr,
-        ITEM_LIST => FragmentKind::Items,
         _ => {
             // Unknown , Just guess it is `Items`
             FragmentKind::Items
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs
index e97b814739..bbbc391c4f 100644
--- a/crates/ra_hir_ty/src/infer.rs
+++ b/crates/ra_hir_ty/src/infer.rs
@@ -196,12 +196,7 @@ struct InferenceContext<'a, D: HirDatabase> {
     trait_env: Arc<TraitEnvironment>,
     obligations: Vec<Obligation>,
     result: InferenceResult,
-    /// The return type of the function being inferred, or the closure if we're
-    /// currently within one.
-    ///
-    /// We might consider using a nested inference context for checking
-    /// closures, but currently this is the only field that will change there,
-    /// so it doesn't make sense.
+    /// The return type of the function being inferred.
     return_ty: Ty,
 
     /// Impls of `CoerceUnsized` used in coercion.
@@ -460,7 +455,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
     }
 
     fn infer_body(&mut self) {
-        self.infer_expr_coerce(self.body.body_expr, &Expectation::has_type(self.return_ty.clone()));
+        self.infer_expr(self.body.body_expr, &Expectation::has_type(self.return_ty.clone()));
     }
 
     fn resolve_into_iter_item(&self) -> Option<TypeAliasId> {
diff --git a/crates/ra_hir_ty/src/infer/coerce.rs b/crates/ra_hir_ty/src/infer/coerce.rs
index 83c0c2c3f3..0f4dac45ed 100644
--- a/crates/ra_hir_ty/src/infer/coerce.rs
+++ b/crates/ra_hir_ty/src/infer/coerce.rs
@@ -134,10 +134,6 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
                 }
             }
 
-            (ty_app!(TypeCtor::Closure { .. }, params), ty_app!(TypeCtor::FnPtr { .. })) => {
-                from_ty = params[0].clone();
-            }
-
             _ => {}
         }
 
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs
index 3af05394c6..8be5679177 100644
--- a/crates/ra_hir_ty/src/infer/expr.rs
+++ b/crates/ra_hir_ty/src/infer/expr.rs
@@ -41,7 +41,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
 
     /// Infer type of expression with possibly implicit coerce to the expected type.
     /// Return the type after possible coercion.
-    pub(super) fn infer_expr_coerce(&mut self, expr: ExprId, expected: &Expectation) -> Ty {
+    fn infer_expr_coerce(&mut self, expr: ExprId, expected: &Expectation) -> Ty {
         let ty = self.infer_expr_inner(expr, &expected);
         let ty = if !self.coerce(&ty, &expected.ty) {
             self.result
@@ -102,7 +102,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
                 self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
                 Ty::unit()
             }
-            Expr::Lambda { body, args, ret_type, arg_types } => {
+            Expr::Lambda { body, args, arg_types } => {
                 assert_eq!(args.len(), arg_types.len());
 
                 let mut sig_tys = Vec::new();
@@ -118,10 +118,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
                 }
 
                 // add return type
-                let ret_ty = match ret_type {
-                    Some(type_ref) => self.make_ty(type_ref),
-                    None => self.table.new_type_var(),
-                };
+                let ret_ty = self.table.new_type_var();
                 sig_tys.push(ret_ty.clone());
                 let sig_ty = Ty::apply(
                     TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 },
@@ -137,12 +134,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
                 // infer the body.
                 self.coerce(&closure_ty, &expected.ty);
 
-                let prev_ret_ty = std::mem::replace(&mut self.return_ty, ret_ty.clone());
-
-                self.infer_expr_coerce(*body, &Expectation::has_type(ret_ty));
-
-                self.return_ty = prev_ret_ty;
-
+                self.infer_expr(*body, &Expectation::has_type(ret_ty));
                 closure_ty
             }
             Expr::Call { callee, args } => {
@@ -200,9 +192,6 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
             Expr::Return { expr } => {
                 if let Some(expr) = expr {
                     self.infer_expr_coerce(*expr, &Expectation::has_type(self.return_ty.clone()));
-                } else {
-                    let unit = Ty::unit();
-                    self.coerce(&unit, &self.return_ty.clone());
                 }
                 Ty::simple(TypeCtor::Never)
             }
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs
index 92fb4c0817..888dc31166 100644
--- a/crates/ra_hir_ty/src/method_resolution.rs
+++ b/crates/ra_hir_ty/src/method_resolution.rs
@@ -58,7 +58,7 @@ impl CrateImplBlocks {
 
         let crate_def_map = db.crate_def_map(krate);
         for (_module_id, module_data) in crate_def_map.modules.iter() {
-            for &impl_id in module_data.impls.iter() {
+            for impl_id in module_data.scope.impls() {
                 match db.impl_trait(impl_id) {
                     Some(tr) => {
                         res.impls_by_trait.entry(tr.trait_).or_default().push(impl_id);
diff --git a/crates/ra_ide/src/display.rs b/crates/ra_ide/src/display.rs
index fbe89841b0..30617412a6 100644
--- a/crates/ra_ide/src/display.rs
+++ b/crates/ra_ide/src/display.rs
@@ -15,7 +15,7 @@ pub use function_signature::FunctionSignature;
 pub use navigation_target::NavigationTarget;
 pub use structure::{file_structure, StructureNode};
 
-pub(crate) use navigation_target::ToNav;
+pub(crate) use navigation_target::{description_from_symbol, docs_from_symbol, ToNav};
 pub(crate) use short_label::ShortLabel;
 
 pub(crate) fn function_label(node: &ast::FnDef) -> String {
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs
index 35e39f9652..a227bf546c 100644
--- a/crates/ra_ide/src/hover.rs
+++ b/crates/ra_ide/src/hover.rs
@@ -12,7 +12,10 @@ use ra_syntax::{
 
 use crate::{
     db::RootDatabase,
-    display::{macro_label, rust_code_markup, rust_code_markup_with_doc, ShortLabel},
+    display::{
+        description_from_symbol, docs_from_symbol, macro_label, rust_code_markup,
+        rust_code_markup_with_doc, ShortLabel,
+    },
     expand::descend_into_macros,
     references::{classify_name, classify_name_ref, NameKind, NameKind::*},
     FilePosition, FileRange, RangeInfo,
@@ -92,7 +95,11 @@ fn hover_text(docs: Option<String>, desc: Option<String>) -> Option<String> {
     }
 }
 
-fn hover_text_from_name_kind(db: &RootDatabase, name_kind: NameKind) -> Option<String> {
+fn hover_text_from_name_kind(
+    db: &RootDatabase,
+    name_kind: NameKind,
+    no_fallback: &mut bool,
+) -> Option<String> {
     return match name_kind {
         Macro(it) => {
             let src = it.source(db);
@@ -128,7 +135,11 @@ fn hover_text_from_name_kind(db: &RootDatabase, name_kind: NameKind) -> Option<S
             hir::ModuleDef::TypeAlias(it) => from_def_source(db, it),
             hir::ModuleDef::BuiltinType(it) => Some(it.to_string()),
         },
-        Local(_) => None,
+        Local(_) => {
+            // Hover for these shows type names
+            *no_fallback = true;
+            None
+        }
         TypeParam(_) | SelfType(_) => {
             // FIXME: Hover for generic param
             None
@@ -152,35 +163,60 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
 
     let mut res = HoverResult::new();
 
-    if let Some((range, name_kind)) = match_ast! {
+    let mut range = match_ast! {
         match (token.value.parent()) {
             ast::NameRef(name_ref) => {
-                classify_name_ref(db, token.with_value(&name_ref)).map(|d| (name_ref.syntax().text_range(), d.kind))
+                let mut no_fallback = false;
+                if let Some(name_kind) =
+                    classify_name_ref(db, token.with_value(&name_ref)).map(|d| d.kind)
+                {
+                    res.extend(hover_text_from_name_kind(db, name_kind, &mut no_fallback))
+                }
+
+                if res.is_empty() && !no_fallback {
+                    // Fallback index based approach:
+                    let symbols = crate::symbol_index::index_resolve(db, &name_ref);
+                    for sym in symbols {
+                        let docs = docs_from_symbol(db, &sym);
+                        let desc = description_from_symbol(db, &sym);
+                        res.extend(hover_text(docs, desc));
+                    }
+                }
+
+                if !res.is_empty() {
+                    Some(name_ref.syntax().text_range())
+                } else {
+                    None
+                }
             },
             ast::Name(name) => {
-                classify_name(db, token.with_value(&name)).map(|d| (name.syntax().text_range(), d.kind))
+                if let Some(name_kind) = classify_name(db, token.with_value(&name)).map(|d| d.kind) {
+                    res.extend(hover_text_from_name_kind(db, name_kind, &mut true));
+                }
+
+                if !res.is_empty() {
+                    Some(name.syntax().text_range())
+                } else {
+                    None
+                }
             },
             _ => None,
         }
-    } {
-        res.extend(hover_text_from_name_kind(db, name_kind));
+    };
 
-        if !res.is_empty() {
-            return Some(RangeInfo::new(range, res));
-        }
-    }
+    if range.is_none() {
+        let node = token.value.ancestors().find(|n| {
+            ast::Expr::cast(n.clone()).is_some() || ast::Pat::cast(n.clone()).is_some()
+        })?;
+        let frange = FileRange { file_id: position.file_id, range: node.text_range() };
+        res.extend(type_of(db, frange).map(rust_code_markup));
+        range = Some(node.text_range());
+    };
 
-    let node = token
-        .value
-        .ancestors()
-        .find(|n| ast::Expr::cast(n.clone()).is_some() || ast::Pat::cast(n.clone()).is_some())?;
-    let frange = FileRange { file_id: position.file_id, range: node.text_range() };
-    res.extend(type_of(db, frange).map(rust_code_markup));
+    let range = range?;
     if res.is_empty() {
         return None;
     }
-    let range = node.text_range();
-
     Some(RangeInfo::new(range, res))
 }
 
@@ -278,7 +314,7 @@ mod tests {
             &["pub fn foo() -> u32"],
         );
 
-        // Multiple candidates but results are ambiguous.
+        // Multiple results
         check_hover_result(
             r#"
             //- /a.rs
@@ -299,7 +335,7 @@ mod tests {
                 let foo_test = fo<|>o();
             }
         "#,
-            &["{unknown}"],
+            &["pub fn foo() -> &str", "pub fn foo() -> u32", "pub fn foo(a: u32, b: u32)"],
         );
     }
 
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index 8d65e2e08e..9dd6bd3eac 100644
--- a/crates/ra_syntax/src/ast/generated.rs
+++ b/crates/ra_syntax/src/ast/generated.rs
@@ -1426,9 +1426,6 @@ impl LambdaExpr {
     pub fn param_list(&self) -> Option<ParamList> {
         AstChildren::new(&self.syntax).next()
     }
-    pub fn ret_type(&self) -> Option<RetType> {
-        AstChildren::new(&self.syntax).next()
-    }
     pub fn body(&self) -> Option<Expr> {
         AstChildren::new(&self.syntax).next()
     }
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
index a228fa9d6e..9ffa9095bc 100644
--- a/crates/ra_syntax/src/grammar.ron
+++ b/crates/ra_syntax/src/grammar.ron
@@ -426,7 +426,7 @@ Grammar(
         "PathExpr": (options: ["Path"]),
         "LambdaExpr": (
             options: [
-                "ParamList", "RetType",
+                "ParamList",
                 ["body", "Expr"],
             ]
         ),
diff --git a/editors/code/package-lock.json b/editors/code/package-lock.json
index 4c5c13646c..127cdcfa10 100644
--- a/editors/code/package-lock.json
+++ b/editors/code/package-lock.json
@@ -60,9 +60,9 @@
             "dev": true
         },
         "@types/node": {
-            "version": "12.12.21",
-            "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.21.tgz",
-            "integrity": "sha512-8sRGhbpU+ck1n0PGAUgVrWrWdjSW2aqNeyC15W88GRsMpSwzv6RJGlLhE7s2RhVSOdyDmxbqlWSeThq4/7xqlA==",
+            "version": "10.17.6",
+            "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.6.tgz",
+            "integrity": "sha512-0a2X6cgN3RdPBL2MIlR6Lt0KlM7fOFsutuXcdglcOq6WvLnYXgPQSh0Mx6tO1KCAE8MxbHSOSTWDoUxRq+l3DA==",
             "dev": true
         },
         "@types/resolve": {
@@ -81,9 +81,9 @@
             "dev": true
         },
         "@types/vscode": {
-            "version": "1.41.0",
-            "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.41.0.tgz",
-            "integrity": "sha512-7SfeY5u9jgiELwxyLB3z7l6l/GbN9CqpCQGkcRlB7tKRFBxzbz2PoBfGrLxI1vRfUCIq5+hg5vtDHExwq5j3+A==",
+            "version": "1.40.0",
+            "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.40.0.tgz",
+            "integrity": "sha512-5kEIxL3qVRkwhlMerxO7XuMffa+0LBl+iG2TcRa0NsdoeSFLkt/9hJ02jsi/Kvc6y8OVF2N2P2IHP5S4lWf/5w==",
             "dev": true
         },
         "acorn": {
@@ -791,9 +791,9 @@
             }
         },
         "lookpath": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/lookpath/-/lookpath-1.0.4.tgz",
-            "integrity": "sha512-xVFrWlfo7n8VZs1YjBWKkbSIJU7DKE/0Mep62KeT94V1Ui1IY9w5fXfgiCsDIDZkakIYSXSeaW2FLbCqfw9/Cw=="
+            "version": "1.0.3",
+            "resolved": "https://registry.npmjs.org/lookpath/-/lookpath-1.0.3.tgz",
+            "integrity": "sha512-XIdgzlX26g10XnzyZdO/4obybEmfGnZyWQZ2DgmmEfVB79X+n3lhUoIzMe501C6s7RmCpAo66OPegWc+CsxYMg=="
         },
         "magic-string": {
             "version": "0.25.3",
@@ -1140,9 +1140,9 @@
             }
         },
         "rollup": {
-            "version": "1.27.13",
-            "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.27.13.tgz",
-            "integrity": "sha512-hDi7M07MpmNSDE8YVwGVFA8L7n8jTLJ4lG65nMAijAyqBe//rtu4JdxjUBE7JqXfdpqxqDTbCDys9WcqdpsQvw==",
+            "version": "1.27.9",
+            "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.27.9.tgz",
+            "integrity": "sha512-8AfW4cJTPZfG6EXWwT/ujL4owUsDI1Xl8J1t+hvK4wDX81F5I4IbwP9gvGbHzxnV19fnU4rRABZQwZSX9J402Q==",
             "dev": true,
             "requires": {
                 "@types/estree": "*",
@@ -1514,9 +1514,9 @@
             "dev": true
         },
         "vsce": {
-            "version": "1.71.0",
-            "resolved": "https://registry.npmjs.org/vsce/-/vsce-1.71.0.tgz",
-            "integrity": "sha512-7k+LPC4oJYPyyxs0a5nh4A8CleQ6+2EMPiAiX/bDyN+PmwJFm2FFPqLRxdIsIWfFnkW4ZMQBf10+W62dCRd9kQ==",
+            "version": "1.70.0",
+            "resolved": "https://registry.npmjs.org/vsce/-/vsce-1.70.0.tgz",
+            "integrity": "sha512-mBTbVrWL348jODwfmaR+yXrlzb8EABGCT067C4shKOXriWiuMQi4/uCbFm6TUBcfnzTYLJv+DKa0VnKU8yEAjA==",
             "dev": true,
             "requires": {
                 "azure-devops-node-api": "^7.2.0",
@@ -1547,12 +1547,12 @@
             "integrity": "sha512-k9akfglxWgr0dtLNscq2uBq48XJwnhf4EaDxn05KQowRwR0DkNML0zeYqFRLtXZe6x5vpL5ppyu4o6GqL+23YQ=="
         },
         "vscode-languageclient": {
-            "version": "6.0.0-next.9",
-            "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-6.0.0-next.9.tgz",
-            "integrity": "sha512-NEpeeFM9FKrrRqlBHXGfwpkhtnjruDz3zfFBP+Cymr10qigAEtE/JsODJsIG/ErGqjh3/JXxu8SUOVTGu5oK+w==",
+            "version": "6.0.0-next.8",
+            "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-6.0.0-next.8.tgz",
+            "integrity": "sha512-452jskmuT7YKYnPd5uh7aELK4M25OITcnBq4ylPIyUtE5LQRgA9N9pR9NrviTTX/Hh6q6VGzm70OK9SpMO/zcA==",
             "requires": {
                 "semver": "^6.3.0",
-                "vscode-languageserver-protocol": "^3.15.0-next.14"
+                "vscode-languageserver-protocol": "^3.15.0-next.13"
             },
             "dependencies": {
                 "semver": {
@@ -1563,9 +1563,9 @@
             }
         },
         "vscode-languageserver-protocol": {
-            "version": "3.15.0-next.14",
-            "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.0-next.14.tgz",
-            "integrity": "sha512-xUwwno6Q6RFd2Z2EWV9D3dQlsKPnHyiZMNWq+EC7JJdp2WH1gRlD+KPX4UGRCnJK0WI5omqHV313IESPwRY5xA==",
+            "version": "3.15.0-next.13",
+            "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.0-next.13.tgz",
+            "integrity": "sha512-2UGxOKc5VHav15n3zY5dtaOXGL/JuV0K2Mem/n6lhF8i3vaqIAnKv004SPU0flYHXIfCcQM7kCL+nwWVJ1K1qw==",
             "requires": {
                 "vscode-jsonrpc": "^5.0.0-next.5",
                 "vscode-languageserver-types": "^3.15.0-next.9"
@@ -1577,9 +1577,9 @@
             "integrity": "sha512-Rl/8qJ6932nrHCdPn+9y0x08uLVQaSLRG+U4JzhyKpWU4eJbVaDRoAcz1Llj7CErJGbPr6kdBvShPy5fRfR+Uw=="
         },
         "vscode-test": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-1.3.0.tgz",
-            "integrity": "sha512-LddukcBiSU2FVTDr3c1D8lwkiOvwlJdDL2hqVbn6gIz+rpTqUCkMZSKYm94Y1v0WXlHSDQBsXyY+tchWQgGVsw==",
+            "version": "1.2.3",
+            "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-1.2.3.tgz",
+            "integrity": "sha512-mKRTNso33NaUULiPBFg6zRjyntjcCpIgkrogyPQuKlvoQREQR8jLKN5UD4L5rkTSD+oBhcKtaLR2/g34FexURw==",
             "dev": true,
             "requires": {
                 "http-proxy-agent": "^2.1.0",
diff --git a/editors/code/package.json b/editors/code/package.json
index f75fafeb9e..f2e8e647e3 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -13,7 +13,7 @@
         "Other"
     ],
     "engines": {
-        "vscode": "^1.41.0"
+        "vscode": "^1.40.0"
     },
     "scripts": {
         "vscode:prepublish": "npm run compile",
@@ -32,20 +32,20 @@
         "trailingComma": "all"
     },
     "dependencies": {
-        "lookpath": "^1.0.4",
+        "lookpath": "^1.0.3",
         "seedrandom": "^3.0.5",
-        "vscode-languageclient": "^6.0.0-next.9"
+        "vscode-languageclient": "^6.0.0-next.8"
     },
     "devDependencies": {
         "@types/glob": "^7.1.1",
         "@types/mocha": "^5.2.7",
-        "@types/node": "^12.12.21",
+        "@types/node": "^10.17.6",
         "@types/seedrandom": "^2.4.28",
-        "@types/vscode": "^1.41.0",
+        "@types/vscode": "^1.40.0",
         "glob": "^7.1.6",
         "mocha": "^6.2.2",
         "prettier": "^1.19.1",
-        "rollup": "^1.27.13",
+        "rollup": "^1.27.9",
         "rollup-plugin-commonjs": "^10.1.0",
         "rollup-plugin-node-resolve": "^5.2.0",
         "rollup-plugin-sourcemaps": "^0.4.2",
@@ -55,8 +55,8 @@
         "tslint-config-prettier": "^1.18.0",
         "tslint-plugin-prettier": "^2.0.1",
         "typescript": "^3.7.3",
-        "vsce": "^1.71.0",
-        "vscode-test": "^1.3.0"
+        "vsce": "^1.70.0",
+        "vscode-test": "^1.2.3"
     },
     "activationEvents": [
         "onLanguage:rust",
diff --git a/editors/code/src/commands/cargo_watch.ts b/editors/code/src/commands/cargo_watch.ts
index ac62bdd48d..748be535cc 100644
--- a/editors/code/src/commands/cargo_watch.ts
+++ b/editors/code/src/commands/cargo_watch.ts
@@ -111,13 +111,8 @@ export class CargoWatchProvider implements vscode.Disposable {
             },
         );
 
-        if (!this.cargoProcess) {
-            vscode.window.showErrorMessage('Cargo Watch failed to start');
-            return;
-        }
-
         const stdoutData = new LineBuffer();
-        this.cargoProcess.stdout?.on('data', (s: string) => {
+        this.cargoProcess.stdout.on('data', (s: string) => {
             stdoutData.processOutput(s, line => {
                 this.logInfo(line);
                 try {
@@ -129,7 +124,7 @@ export class CargoWatchProvider implements vscode.Disposable {
         });
 
         const stderrData = new LineBuffer();
-        this.cargoProcess.stderr?.on('data', (s: string) => {
+        this.cargoProcess.stderr.on('data', (s: string) => {
             stderrData.processOutput(s, line => {
                 this.logError('Error on cargo-watch : {\n' + line + '}\n');
             });


Test patch:
diff --git a/crates/ra_hir_def/src/nameres/tests.rs b/crates/ra_hir_def/src/nameres/tests.rs
index 61cdd768e8..4e968bcc84 100644
--- a/crates/ra_hir_def/src/nameres/tests.rs
+++ b/crates/ra_hir_def/src/nameres/tests.rs
@@ -32,27 +32,22 @@ fn render_crate_def_map(map: &CrateDefMap) -> String {
         *buf += path;
         *buf += "\n";
 
-        let mut entries = map.modules[module]
-            .scope
-            .items
-            .iter()
-            .map(|(name, res)| (name, res.def))
-            .collect::<Vec<_>>();
-        entries.sort_by_key(|(name, _)| *name);
+        let mut entries = map.modules[module].scope.collect_resolutions();
+        entries.sort_by_key(|(name, _)| name.clone());
 
         for (name, res) in entries {
             *buf += &format!("{}:", name);
 
-            if res.types.is_some() {
+            if res.def.types.is_some() {
                 *buf += " t";
             }
-            if res.values.is_some() {
+            if res.def.values.is_some() {
                 *buf += " v";
             }
-            if res.macros.is_some() {
+            if res.def.macros.is_some() {
                 *buf += " m";
             }
-            if res.is_none() {
+            if res.def.is_none() {
                 *buf += " _";
             }
 
@@ -587,6 +582,6 @@ mod b {
     ⋮T: v
     ⋮
     ⋮crate::a
-    ⋮T: t v    
+    ⋮T: t v
 "###);
 }
diff --git a/crates/ra_hir_def/src/nameres/tests/incremental.rs b/crates/ra_hir_def/src/nameres/tests/incremental.rs
index 903a227719..ef2e9435cf 100644
--- a/crates/ra_hir_def/src/nameres/tests/incremental.rs
+++ b/crates/ra_hir_def/src/nameres/tests/incremental.rs
@@ -116,7 +116,7 @@ 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);
+            assert_eq!(module_data.scope.collect_resolutions().len(), 1);
         });
         assert!(format!("{:?}", events).contains("crate_def_map"), "{:#?}", events)
     }
@@ -126,7 +126,7 @@ 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);
+            assert_eq!(module_data.scope.collect_resolutions().len(), 1);
         });
         assert!(!format!("{:?}", events).contains("crate_def_map"), "{:#?}", events)
     }
diff --git a/crates/ra_hir_def/src/nameres/tests/macros.rs b/crates/ra_hir_def/src/nameres/tests/macros.rs
index cfa4ecb1af..d104f5993f 100644
--- a/crates/ra_hir_def/src/nameres/tests/macros.rs
+++ b/crates/ra_hir_def/src/nameres/tests/macros.rs
@@ -610,7 +610,7 @@ fn expand_derive() {
         struct Foo;
         ",
     );
-    assert_eq!(map.modules[map.root].impls.len(), 1);
+    assert_eq!(map.modules[map.root].scope.impls().len(), 1);
 }
 
 #[test]
@@ -622,5 +622,5 @@ fn expand_multiple_derive() {
         struct Foo;
         ",
     );
-    assert_eq!(map.modules[map.root].impls.len(), 2);
+    assert_eq!(map.modules[map.root].scope.impls().len(), 2);
 }
diff --git a/crates/ra_hir_ty/src/test_db.rs b/crates/ra_hir_ty/src/test_db.rs
index 476f6df52a..1a31b587bb 100644
--- a/crates/ra_hir_ty/src/test_db.rs
+++ b/crates/ra_hir_ty/src/test_db.rs
@@ -98,7 +98,7 @@ impl TestDB {
                     }
                 }
 
-                for &impl_id in crate_def_map[module_id].impls.iter() {
+                for impl_id in crate_def_map[module_id].scope.impls() {
                     let impl_data = self.impl_data(impl_id);
                     for item in impl_data.items.iter() {
                         if let AssocItemId::FunctionId(f) = item {
diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs
index d724ee1223..d447b45718 100644
--- a/crates/ra_hir_ty/src/tests.rs
+++ b/crates/ra_hir_ty/src/tests.rs
@@ -182,7 +182,7 @@ fn visit_module(
             _ => (),
         }
     }
-    for &impl_id in crate_def_map[module_id].impls.iter() {
+    for impl_id in crate_def_map[module_id].scope.impls() {
         let impl_data = db.impl_data(impl_id);
         for &item in impl_data.items.iter() {
             match item {
diff --git a/crates/ra_hir_ty/src/tests/coercion.rs b/crates/ra_hir_ty/src/tests/coercion.rs
index 7e99a42edc..ac9e3872a5 100644
--- a/crates/ra_hir_ty/src/tests/coercion.rs
+++ b/crates/ra_hir_ty/src/tests/coercion.rs
@@ -369,22 +369,6 @@ fn test() {
     );
 }
 
-#[test]
-fn return_coerce_unknown() {
-    assert_snapshot!(
-        infer_with_mismatches(r#"
-fn foo() -> u32 {
-    return unknown;
-}
-"#, true),
-        @r###"
-    [17; 40) '{     ...own; }': !
-    [23; 37) 'return unknown': !
-    [30; 37) 'unknown': u32
-    "###
-    );
-}
-
 #[test]
 fn coerce_autoderef() {
     assert_snapshot!(
@@ -456,73 +440,3 @@ fn test() {
     "###
     );
 }
-
-#[test]
-fn closure_return_coerce() {
-    assert_snapshot!(
-        infer_with_mismatches(r#"
-fn foo() {
-    let x = || {
-        if true {
-            return &1u32;
-        }
-        &&1u32
-    };
-}
-"#, true),
-        @r###"
-    [10; 106) '{     ...  }; }': ()
-    [20; 21) 'x': || -> &u32
-    [24; 103) '|| {  ...     }': || -> &u32
-    [27; 103) '{     ...     }': &u32
-    [37; 82) 'if tru...     }': ()
-    [40; 44) 'true': bool
-    [45; 82) '{     ...     }': !
-    [59; 71) 'return &1u32': !
-    [66; 71) '&1u32': &u32
-    [67; 71) '1u32': u32
-    [91; 97) '&&1u32': &&u32
-    [92; 97) '&1u32': &u32
-    [93; 97) '1u32': u32
-    "###
-    );
-}
-
-#[test]
-fn coerce_fn_item_to_fn_ptr() {
-    assert_snapshot!(
-        infer_with_mismatches(r#"
-fn foo(x: u32) -> isize { 1 }
-fn test() {
-    let f: fn(u32) -> isize = foo;
-}
-"#, true),
-        @r###"
-    [8; 9) 'x': u32
-    [25; 30) '{ 1 }': isize
-    [27; 28) '1': isize
-    [41; 79) '{     ...foo; }': ()
-    [51; 52) 'f': fn(u32) -> isize
-    [73; 76) 'foo': fn foo(u32) -> isize
-    "###
-    );
-}
-
-#[test]
-fn coerce_closure_to_fn_ptr() {
-    assert_snapshot!(
-        infer_with_mismatches(r#"
-fn test() {
-    let f: fn(u32) -> isize = |x| { 1 };
-}
-"#, true),
-        @r###"
-    [11; 55) '{     ...1 }; }': ()
-    [21; 22) 'f': fn(u32) -> isize
-    [43; 52) '|x| { 1 }': |u32| -> isize
-    [44; 45) 'x': u32
-    [47; 52) '{ 1 }': isize
-    [49; 50) '1': isize
-    "###
-    );
-}
diff --git a/crates/ra_hir_ty/src/tests/macros.rs b/crates/ra_hir_ty/src/tests/macros.rs
index 7fdbf996f4..812f171db8 100644
--- a/crates/ra_hir_ty/src/tests/macros.rs
+++ b/crates/ra_hir_ty/src/tests/macros.rs
@@ -182,25 +182,6 @@ fn test() { S.foo()<|>; }
     assert_eq!(t, "u128");
 }
 
-#[test]
-fn infer_impl_items_generated_by_macros() {
-    let t = type_at(
-        r#"
-//- /main.rs
-macro_rules! m {
-    () => (fn foo(&self) -> u128 {0})
-}
-struct S;
-impl S {
-    m!();
-}
-
-fn test() { S.foo()<|>; }
-"#,
-    );
-    assert_eq!(t, "u128");
-}
-
 #[test]
 fn infer_macro_with_dollar_crate_is_correct_in_expr() {
     let (db, pos) = TestDB::with_position(
diff --git a/crates/ra_hir_ty/src/tests/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs
index 6fe647a5e3..18976c9aee 100644
--- a/crates/ra_hir_ty/src/tests/simple.rs
+++ b/crates/ra_hir_ty/src/tests/simple.rs
@@ -1606,58 +1606,3 @@ fn main() {
     );
     assert_eq!(t, "u32");
 }
-
-#[test]
-fn closure_return() {
-    assert_snapshot!(
-        infer(r#"
-fn foo() -> u32 {
-    let x = || -> usize { return 1; };
-}
-"#),
-        @r###"
-    [17; 59) '{     ...; }; }': ()
-    [27; 28) 'x': || -> usize
-    [31; 56) '|| -> ...n 1; }': || -> usize
-    [43; 56) '{ return 1; }': !
-    [45; 53) 'return 1': !
-    [52; 53) '1': usize
-    "###
-    );
-}
-
-#[test]
-fn closure_return_unit() {
-    assert_snapshot!(
-        infer(r#"
-fn foo() -> u32 {
-    let x = || { return; };
-}
-"#),
-        @r###"
-    [17; 48) '{     ...; }; }': ()
-    [27; 28) 'x': || -> ()
-    [31; 45) '|| { return; }': || -> ()
-    [34; 45) '{ return; }': !
-    [36; 42) 'return': !
-    "###
-    );
-}
-
-#[test]
-fn closure_return_inferred() {
-    assert_snapshot!(
-        infer(r#"
-fn foo() -> u32 {
-    let x = || { "test" };
-}
-"#),
-        @r###"
-    [17; 47) '{     ..." }; }': ()
-    [27; 28) 'x': || -> &str
-    [31; 44) '|| { "test" }': || -> &str
-    [34; 44) '{ "test" }': &str
-    [36; 42) '"test"': &str
-    "###
-    );
-}
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs
index 76e2198b66..2d92a5eec2 100644
--- a/crates/ra_hir_ty/src/tests/traits.rs
+++ b/crates/ra_hir_ty/src/tests/traits.rs
@@ -393,11 +393,11 @@ fn test() -> u64 {
     [54; 55) 'a': S
     [58; 59) 'S': S(fn(u32) -> u64) -> S
     [58; 68) 'S(|i| 2*i)': S
-    [60; 67) '|i| 2*i': |u32| -> u64
-    [61; 62) 'i': u32
-    [64; 65) '2': u32
-    [64; 67) '2*i': u32
-    [66; 67) 'i': u32
+    [60; 67) '|i| 2*i': |i32| -> i32
+    [61; 62) 'i': i32
+    [64; 65) '2': i32
+    [64; 67) '2*i': i32
+    [66; 67) 'i': i32
     [78; 79) 'b': u64
     [82; 83) 'a': S
     [82; 85) 'a.0': fn(u32) -> u64