Repository: rust-lang/rust-analyzer
Pull request #19016 (2025-01-24 11:58:03)

fix: Fix `ItemScope` not recording glob imports
This caused us other code to incorrectly assume in dealing with a declaration when in fact it was dealing with a glob imported definition. This can cause hangs with certain setups that involve glob imports and local item block modules (not sure on the exact setup needed), it also means we do a lot more work in some cases (or even wrong work).


Patch:
diff --git a/crates/hir-def/src/import_map.rs b/crates/hir-def/src/import_map.rs
index a3ffdf770e..04c088b5a5 100644
--- a/crates/hir-def/src/import_map.rs
+++ b/crates/hir-def/src/import_map.rs
@@ -10,6 +10,7 @@ use rustc_hash::FxHashSet;
 use smallvec::SmallVec;
 use span::Edition;
 use stdx::{format_to, TupleExt};
+use syntax::ToSmolStr;
 use triomphe::Arc;
 
 use crate::{
@@ -87,9 +88,9 @@ impl ImportMap {
             .iter()
             // We've only collected items, whose name cannot be tuple field so unwrapping is fine.
             .flat_map(|(&item, (info, _))| {
-                info.iter()
-                    .enumerate()
-                    .map(move |(idx, info)| (item, info.name.as_str(), idx as u32))
+                info.iter().enumerate().map(move |(idx, info)| {
+                    (item, info.name.unescaped().display(db.upcast()).to_smolstr(), idx as u32)
+                })
             })
             .collect();
         importables.sort_by(|(_, l_info, _), (_, r_info, _)| {
@@ -168,6 +169,7 @@ impl ImportMap {
                         match import {
                             ImportOrExternCrate::ExternCrate(id) => Some(id.into()),
                             ImportOrExternCrate::Import(id) => Some(id.import.into()),
+                            ImportOrExternCrate::Glob(id) => Some(id.into()),
                         }
                     } else {
                         match item {
@@ -440,7 +442,7 @@ pub fn search_dependencies(
 }
 
 fn search_maps(
-    _db: &dyn DefDatabase,
+    db: &dyn DefDatabase,
     import_maps: &[Arc<ImportMap>],
     mut stream: fst::map::Union<'_>,
     query: &Query,
@@ -463,7 +465,11 @@ fn search_maps(
                         .then(|| (item, &import_infos[info_idx as usize]))
                 })
                 .filter(|&(_, info)| {
-                    query.search_mode.check(&query.query, query.case_sensitive, info.name.as_str())
+                    query.search_mode.check(
+                        &query.query,
+                        query.case_sensitive,
+                        &info.name.unescaped().display(db.upcast()).to_smolstr(),
+                    )
                 });
             res.extend(iter.map(TupleExt::head));
         }
diff --git a/crates/hir-def/src/item_scope.rs b/crates/hir-def/src/item_scope.rs
index 0fec767410..0ece878b83 100644
--- a/crates/hir-def/src/item_scope.rs
+++ b/crates/hir-def/src/item_scope.rs
@@ -31,32 +31,88 @@ pub struct PerNsGlobImports {
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub enum ImportOrExternCrate {
+    Glob(UseId),
     Import(ImportId),
     ExternCrate(ExternCrateId),
 }
 
+impl From<ImportOrGlob> for ImportOrExternCrate {
+    fn from(value: ImportOrGlob) -> Self {
+        match value {
+            ImportOrGlob::Glob(it) => ImportOrExternCrate::Glob(it),
+            ImportOrGlob::Import(it) => ImportOrExternCrate::Import(it),
+        }
+    }
+}
+
+impl From<ImportType> for ImportOrExternCrate {
+    fn from(value: ImportType) -> Self {
+        match value {
+            ImportType::Glob(it) => ImportOrExternCrate::Glob(it),
+            ImportType::Import(it) => ImportOrExternCrate::Import(it),
+            ImportType::ExternCrate(it) => ImportOrExternCrate::ExternCrate(it),
+        }
+    }
+}
+
+impl ImportOrExternCrate {
+    pub fn into_import(self) -> Option<ImportOrGlob> {
+        match self {
+            ImportOrExternCrate::Import(it) => Some(ImportOrGlob::Import(it)),
+            ImportOrExternCrate::Glob(it) => Some(ImportOrGlob::Glob(it)),
+            _ => None,
+        }
+    }
+}
+
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-pub(crate) enum ImportType {
-    Import(ImportId),
+pub enum ImportOrGlob {
     Glob(UseId),
-    ExternCrate(ExternCrateId),
+    Import(ImportId),
 }
 
-impl ImportOrExternCrate {
+impl ImportOrGlob {
     pub fn into_import(self) -> Option<ImportId> {
         match self {
-            ImportOrExternCrate::Import(it) => Some(it),
+            ImportOrGlob::Import(it) => Some(it),
             _ => None,
         }
     }
 }
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub(crate) enum ImportType {
+    Import(ImportId),
+    Glob(UseId),
+    ExternCrate(ExternCrateId),
+}
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub enum ImportOrDef {
     Import(ImportId),
+    Glob(UseId),
     ExternCrate(ExternCrateId),
     Def(ModuleDefId),
 }
+
+impl From<ImportOrExternCrate> for ImportOrDef {
+    fn from(value: ImportOrExternCrate) -> Self {
+        match value {
+            ImportOrExternCrate::Import(it) => ImportOrDef::Import(it),
+            ImportOrExternCrate::Glob(it) => ImportOrDef::Glob(it),
+            ImportOrExternCrate::ExternCrate(it) => ImportOrDef::ExternCrate(it),
+        }
+    }
+}
+
+impl From<ImportOrGlob> for ImportOrDef {
+    fn from(value: ImportOrGlob) -> Self {
+        match value {
+            ImportOrGlob::Import(it) => ImportOrDef::Import(it),
+            ImportOrGlob::Glob(it) => ImportOrDef::Glob(it),
+        }
+    }
+}
+
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
 pub struct ImportId {
     pub import: UseId,
@@ -96,8 +152,8 @@ pub struct ItemScope {
 
     // the resolutions of the imports of this scope
     use_imports_types: FxHashMap<ImportOrExternCrate, ImportOrDef>,
-    use_imports_values: FxHashMap<ImportId, ImportOrDef>,
-    use_imports_macros: FxHashMap<ImportId, ImportOrDef>,
+    use_imports_values: FxHashMap<ImportOrGlob, ImportOrDef>,
+    use_imports_macros: FxHashMap<ImportOrGlob, ImportOrDef>,
 
     use_decls: Vec<UseId>,
     extern_crate_decls: Vec<ExternCrateId>,
@@ -162,7 +218,7 @@ impl ItemScope {
             .map(move |name| (name, self.get(name)))
     }
 
-    pub fn values(&self) -> impl Iterator<Item = (&Name, Item<ModuleDefId, ImportId>)> + '_ {
+    pub fn values(&self) -> impl Iterator<Item = (&Name, Item<ModuleDefId, ImportOrGlob>)> + '_ {
         self.values.iter().map(|(n, &i)| (n, i))
     }
 
@@ -172,7 +228,7 @@ impl ItemScope {
         self.types.iter().map(|(n, &i)| (n, i))
     }
 
-    pub fn macros(&self) -> impl Iterator<Item = (&Name, Item<MacroId, ImportId>)> + '_ {
+    pub fn macros(&self) -> impl Iterator<Item = (&Name, Item<MacroId, ImportOrGlob>)> + '_ {
         self.macros.iter().map(|(n, &i)| (n, i))
     }
 
@@ -183,6 +239,7 @@ impl ItemScope {
             .filter_map(ImportOrExternCrate::into_import)
             .chain(self.use_imports_values.keys().copied())
             .chain(self.use_imports_macros.keys().copied())
+            .filter_map(ImportOrGlob::into_import)
             .sorted()
             .dedup()
     }
@@ -192,7 +249,7 @@ impl ItemScope {
 
         let mut def_map;
         let mut scope = self;
-        while let Some(&m) = scope.use_imports_macros.get(&import) {
+        while let Some(&m) = scope.use_imports_macros.get(&ImportOrGlob::Import(import)) {
             match m {
                 ImportOrDef::Import(i) => {
                     let module_id = i.import.lookup(db).container;
@@ -224,7 +281,7 @@ impl ItemScope {
             }
         }
         let mut scope = self;
-        while let Some(&m) = scope.use_imports_values.get(&import) {
+        while let Some(&m) = scope.use_imports_values.get(&ImportOrGlob::Import(import)) {
             match m {
                 ImportOrDef::Import(i) => {
                     let module_id = i.import.lookup(db).container;
@@ -514,29 +571,11 @@ impl ItemScope {
                         }
                         _ => _ = glob_imports.types.remove(&lookup),
                     }
-                    let import = match import {
-                        Some(ImportType::ExternCrate(extern_crate)) => {
-                            Some(ImportOrExternCrate::ExternCrate(extern_crate))
-                        }
-                        Some(ImportType::Import(import)) => {
-                            Some(ImportOrExternCrate::Import(import))
-                        }
-                        None | Some(ImportType::Glob(_)) => None,
-                    };
+                    let import = import.map(Into::into);
                     let prev = std::mem::replace(&mut fld.import, import);
                     if let Some(import) = import {
-                        self.use_imports_types.insert(
-                            import,
-                            match prev {
-                                Some(ImportOrExternCrate::Import(import)) => {
-                                    ImportOrDef::Import(import)
-                                }
-                                Some(ImportOrExternCrate::ExternCrate(import)) => {
-                                    ImportOrDef::ExternCrate(import)
-                                }
-                                None => ImportOrDef::Def(fld.def),
-                            },
-                        );
+                        self.use_imports_types
+                            .insert(import, prev.map_or(ImportOrDef::Def(fld.def), Into::into));
                     }
                     entry.insert(fld);
                     changed = true;
@@ -552,28 +591,12 @@ impl ItemScope {
                         }
                         _ => {
                             if glob_imports.types.remove(&lookup) {
-                                let import = match import {
-                                    Some(ImportType::ExternCrate(extern_crate)) => {
-                                        Some(ImportOrExternCrate::ExternCrate(extern_crate))
-                                    }
-                                    Some(ImportType::Import(import)) => {
-                                        Some(ImportOrExternCrate::Import(import))
-                                    }
-                                    None | Some(ImportType::Glob(_)) => None,
-                                };
+                                let import = import.map(Into::into);
                                 let prev = std::mem::replace(&mut fld.import, import);
                                 if let Some(import) = import {
                                     self.use_imports_types.insert(
                                         import,
-                                        match prev {
-                                            Some(ImportOrExternCrate::Import(import)) => {
-                                                ImportOrDef::Import(import)
-                                            }
-                                            Some(ImportOrExternCrate::ExternCrate(import)) => {
-                                                ImportOrDef::ExternCrate(import)
-                                            }
-                                            None => ImportOrDef::Def(fld.def),
-                                        },
+                                        prev.map_or(ImportOrDef::Def(fld.def), Into::into),
                                     );
                                 }
                                 cov_mark::hit!(import_shadowed);
@@ -597,18 +620,14 @@ impl ItemScope {
                         _ => _ = glob_imports.values.remove(&lookup),
                     }
                     let import = match import {
-                        Some(ImportType::Import(import)) => Some(import),
+                        Some(ImportType::Import(import)) => Some(ImportOrGlob::Import(import)),
+                        Some(ImportType::Glob(u)) => Some(ImportOrGlob::Glob(u)),
                         _ => None,
                     };
                     let prev = std::mem::replace(&mut fld.import, import);
                     if let Some(import) = import {
-                        self.use_imports_values.insert(
-                            import,
-                            match prev {
-                                Some(import) => ImportOrDef::Import(import),
-                                None => ImportOrDef::Def(fld.def),
-                            },
-                        );
+                        self.use_imports_values
+                            .insert(import, prev.map_or(ImportOrDef::Def(fld.def), Into::into));
                     }
                     entry.insert(fld);
                     changed = true;
@@ -616,19 +635,16 @@ impl ItemScope {
                 Entry::Occupied(mut entry) if !matches!(import, Some(ImportType::Glob(..))) => {
                     if glob_imports.values.remove(&lookup) {
                         cov_mark::hit!(import_shadowed);
+
                         let import = match import {
-                            Some(ImportType::Import(import)) => Some(import),
+                            Some(ImportType::Import(import)) => Some(ImportOrGlob::Import(import)),
+                            Some(ImportType::Glob(u)) => Some(ImportOrGlob::Glob(u)),
                             _ => None,
                         };
                         let prev = std::mem::replace(&mut fld.import, import);
                         if let Some(import) = import {
-                            self.use_imports_values.insert(
-                                import,
-                                match prev {
-                                    Some(import) => ImportOrDef::Import(import),
-                                    None => ImportOrDef::Def(fld.def),
-                                },
-                            );
+                            self.use_imports_values
+                                .insert(import, prev.map_or(ImportOrDef::Def(fld.def), Into::into));
                         }
                         entry.insert(fld);
                         changed = true;
@@ -649,17 +665,15 @@ impl ItemScope {
                         _ => _ = glob_imports.macros.remove(&lookup),
                     }
                     let import = match import {
-                        Some(ImportType::Import(import)) => Some(import),
+                        Some(ImportType::Import(import)) => Some(ImportOrGlob::Import(import)),
+                        Some(ImportType::Glob(u)) => Some(ImportOrGlob::Glob(u)),
                         _ => None,
                     };
                     let prev = std::mem::replace(&mut fld.import, import);
                     if let Some(import) = import {
                         self.use_imports_macros.insert(
                             import,
-                            match prev {
-                                Some(import) => ImportOrDef::Import(import),
-                                None => ImportOrDef::Def(fld.def.into()),
-                            },
+                            prev.map_or_else(|| ImportOrDef::Def(fld.def.into()), Into::into),
                         );
                     }
                     entry.insert(fld);
@@ -669,17 +683,15 @@ impl ItemScope {
                     if glob_imports.macros.remove(&lookup) {
                         cov_mark::hit!(import_shadowed);
                         let import = match import {
-                            Some(ImportType::Import(import)) => Some(import),
+                            Some(ImportType::Import(import)) => Some(ImportOrGlob::Import(import)),
+                            Some(ImportType::Glob(u)) => Some(ImportOrGlob::Glob(u)),
                             _ => None,
                         };
                         let prev = std::mem::replace(&mut fld.import, import);
                         if let Some(import) = import {
                             self.use_imports_macros.insert(
                                 import,
-                                match prev {
-                                    Some(import) => ImportOrDef::Import(import),
-                                    None => ImportOrDef::Def(fld.def.into()),
-                                },
+                                prev.map_or_else(|| ImportOrDef::Def(fld.def.into()), Into::into),
                             );
                         }
                         entry.insert(fld);
@@ -704,16 +716,27 @@ impl ItemScope {
             .map(|def| &mut def.vis)
             .chain(self.values.values_mut().map(|def| &mut def.vis))
             .chain(self.unnamed_trait_imports.values_mut().map(|def| &mut def.vis))
-            .for_each(|vis| {
-                *vis = Visibility::Module(this_module, VisibilityExplicitness::Implicit)
+            .for_each(|vis| match vis {
+                &mut Visibility::Module(_, visibility_explicitness) => {
+                    *vis = Visibility::Module(this_module, visibility_explicitness)
+                }
+                Visibility::Public => {
+                    *vis = Visibility::Module(this_module, VisibilityExplicitness::Implicit)
+                }
             });
 
         for mac in self.macros.values_mut() {
             if matches!(mac.def, MacroId::ProcMacroId(_) if mac.import.is_none()) {
                 continue;
             }
-
-            mac.vis = Visibility::Module(this_module, VisibilityExplicitness::Implicit);
+            match mac.vis {
+                Visibility::Module(_, visibility_explicitness) => {
+                    mac.vis = Visibility::Module(this_module, visibility_explicitness)
+                }
+                Visibility::Public => {
+                    mac.vis = Visibility::Module(this_module, VisibilityExplicitness::Implicit)
+                }
+            }
         }
     }
 
@@ -732,20 +755,25 @@ impl ItemScope {
                 buf.push_str(" t");
                 match import {
                     Some(ImportOrExternCrate::Import(_)) => buf.push('i'),
+                    Some(ImportOrExternCrate::Glob(_)) => buf.push('g'),
                     Some(ImportOrExternCrate::ExternCrate(_)) => buf.push('e'),
                     None => (),
                 }
             }
             if let Some(Item { import, .. }) = def.values {
                 buf.push_str(" v");
-                if import.is_some() {
-                    buf.push('i');
+                match import {
+                    Some(ImportOrGlob::Import(_)) => buf.push('i'),
+                    Some(ImportOrGlob::Glob(_)) => buf.push('g'),
+                    None => (),
                 }
             }
             if let Some(Item { import, .. }) = def.macros {
                 buf.push_str(" m");
-                if import.is_some() {
-                    buf.push('i');
+                match import {
+                    Some(ImportOrGlob::Import(_)) => buf.push('i'),
+                    Some(ImportOrGlob::Glob(_)) => buf.push('g'),
+                    None => (),
                 }
             }
             if def.is_none() {
diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs
index 1e4b42dff5..5058d15f34 100644
--- a/crates/hir-def/src/nameres/collector.rs
+++ b/crates/hir-def/src/nameres/collector.rs
@@ -28,7 +28,7 @@ use triomphe::Arc;
 use crate::{
     attr::Attrs,
     db::DefDatabase,
-    item_scope::{ImportId, ImportOrExternCrate, ImportType, PerNsGlobImports},
+    item_scope::{ImportId, ImportOrExternCrate, ImportOrGlob, ImportType, PerNsGlobImports},
     item_tree::{
         self, AttrOwner, FieldsShape, FileItemTreeId, ImportKind, ItemTree, ItemTreeId,
         ItemTreeNode, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId, UseTreeKind,
@@ -527,7 +527,10 @@ impl DefCollector<'_> {
                 // FIXME: This should specifically look for a glob import somehow and record that here
                 self.def_map.prelude = Some((
                     m,
-                    import.and_then(ImportOrExternCrate::into_import).map(|it| it.import),
+                    import
+                        .and_then(ImportOrExternCrate::into_import)
+                        .and_then(ImportOrGlob::into_import)
+                        .map(|it| it.import),
                 ));
             }
             types => {
diff --git a/crates/hir-def/src/nameres/mod_resolution.rs b/crates/hir-def/src/nameres/mod_resolution.rs
index d7e4ca41cd..ab4ffbb2c1 100644
--- a/crates/hir-def/src/nameres/mod_resolution.rs
+++ b/crates/hir-def/src/nameres/mod_resolution.rs
@@ -4,6 +4,7 @@ use base_db::AnchoredPath;
 use hir_expand::{name::Name, HirFileIdExt};
 use limit::Limit;
 use span::EditionedFileId;
+use syntax::ToSmolStr as _;
 
 use crate::{db::DefDatabase, HirFileId};
 
@@ -34,7 +35,7 @@ impl ModDir {
         let path = match attr_path {
             None => {
                 let mut path = self.dir_path.clone();
-                path.push(name.as_str());
+                path.push(&name.unescaped().display_no_db().to_smolstr());
                 path
             }
             Some(attr_path) => {
@@ -65,7 +66,7 @@ impl ModDir {
         name: &Name,
         attr_path: Option<&str>,
     ) -> Result<(EditionedFileId, bool, ModDir), Box<[String]>> {
-        let name = name.as_str();
+        let name = name.unescaped();
 
         let mut candidate_files = ArrayVec::<_, 2>::new();
         match attr_path {
@@ -73,8 +74,16 @@ impl ModDir {
                 candidate_files.push(self.dir_path.join_attr(attr_path, self.root_non_dir_owner))
             }
             None => {
-                candidate_files.push(format!("{}{}.rs", self.dir_path.0, name));
-                candidate_files.push(format!("{}{}/mod.rs", self.dir_path.0, name));
+                candidate_files.push(format!(
+                    "{}{}.rs",
+                    self.dir_path.0,
+                    name.display(db.upcast())
+                ));
+                candidate_files.push(format!(
+                    "{}{}/mod.rs",
+                    self.dir_path.0,
+                    name.display(db.upcast())
+                ));
             }
         };
 
@@ -88,7 +97,7 @@ impl ModDir {
                 let dir_path = if root_dir_owner {
                     DirPath::empty()
                 } else {
-                    DirPath::new(format!("{}/", name))
+                    DirPath::new(format!("{}/", name.display(db.upcast())))
                 };
                 if let Some(mod_dir) = self.child(dir_path, !root_dir_owner) {
                     return Ok((
diff --git a/crates/hir-def/src/per_ns.rs b/crates/hir-def/src/per_ns.rs
index 899dd4afff..339786fc01 100644
--- a/crates/hir-def/src/per_ns.rs
+++ b/crates/hir-def/src/per_ns.rs
@@ -6,7 +6,7 @@
 use bitflags::bitflags;
 
 use crate::{
-    item_scope::{ImportId, ImportOrExternCrate, ItemInNs},
+    item_scope::{ImportId, ImportOrExternCrate, ImportOrGlob, ItemInNs},
     visibility::Visibility,
     MacroId, ModuleDefId,
 };
@@ -36,8 +36,8 @@ pub struct Item<Def, Import = ImportId> {
 }
 
 pub type TypesItem = Item<ModuleDefId, ImportOrExternCrate>;
-pub type ValuesItem = Item<ModuleDefId>;
-pub type MacrosItem = Item<MacroId>;
+pub type ValuesItem = Item<ModuleDefId, ImportOrGlob>;
+pub type MacrosItem = Item<MacroId, ImportOrGlob>;
 
 #[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
 pub struct PerNs {
@@ -59,7 +59,7 @@ impl PerNs {
         PerNs { types: None, values: None, macros: None }
     }
 
-    pub fn values(def: ModuleDefId, vis: Visibility, import: Option<ImportId>) -> PerNs {
+    pub fn values(def: ModuleDefId, vis: Visibility, import: Option<ImportOrGlob>) -> PerNs {
         PerNs { types: None, values: Some(Item { def, vis, import }), macros: None }
     }
 
@@ -84,7 +84,7 @@ impl PerNs {
         }
     }
 
-    pub fn macros(def: MacroId, vis: Visibility, import: Option<ImportId>) -> PerNs {
+    pub fn macros(def: MacroId, vis: Visibility, import: Option<ImportOrGlob>) -> PerNs {
         PerNs { types: None, values: None, macros: Some(Item { def, vis, import }) }
     }
 
@@ -108,7 +108,7 @@ impl PerNs {
         self.values.map(|it| it.def)
     }
 
-    pub fn take_values_import(self) -> Option<(ModuleDefId, Option<ImportId>)> {
+    pub fn take_values_import(self) -> Option<(ModuleDefId, Option<ImportOrGlob>)> {
         self.values.map(|it| (it.def, it.import))
     }
 
@@ -116,7 +116,7 @@ impl PerNs {
         self.macros.map(|it| it.def)
     }
 
-    pub fn take_macros_import(self) -> Option<(MacroId, Option<ImportId>)> {
+    pub fn take_macros_import(self) -> Option<(MacroId, Option<ImportOrGlob>)> {
         self.macros.map(|it| (it.def, it.import))
     }
 
@@ -159,14 +159,12 @@ impl PerNs {
             .map(|it| (ItemInNs::Types(it.def), it.import))
             .into_iter()
             .chain(
-                self.values.map(|it| {
-                    (ItemInNs::Values(it.def), it.import.map(ImportOrExternCrate::Import))
-                }),
+                self.values
+                    .map(|it| (ItemInNs::Values(it.def), it.import.map(ImportOrExternCrate::from))),
             )
             .chain(
-                self.macros.map(|it| {
-                    (ItemInNs::Macros(it.def), it.import.map(ImportOrExternCrate::Import))
-                }),
+                self.macros
+                    .map(|it| (ItemInNs::Macros(it.def), it.import.map(ImportOrExternCrate::from))),
             )
     }
 }
diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs
index 0b9b6da8d5..8c556d8a8c 100644
--- a/crates/hir-def/src/resolver.rs
+++ b/crates/hir-def/src/resolver.rs
@@ -19,7 +19,7 @@ use crate::{
     db::DefDatabase,
     generics::{GenericParams, TypeOrConstParamData},
     hir::{BindingId, ExprId, LabelId},
-    item_scope::{BuiltinShadowMode, ImportId, ImportOrExternCrate, BUILTIN_SCOPE},
+    item_scope::{BuiltinShadowMode, ImportOrExternCrate, ImportOrGlob, BUILTIN_SCOPE},
     lang_item::LangItemTarget,
     nameres::{DefMap, MacroSubNs, ResolvePathResultPrefixInfo},
     path::{ModPath, Path, PathKind},
@@ -107,7 +107,7 @@ pub enum TypeNs {
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub enum ResolveValueResult {
-    ValueNs(ValueNs, Option<ImportId>),
+    ValueNs(ValueNs, Option<ImportOrGlob>),
     Partial(TypeNs, usize, Option<ImportOrExternCrate>),
 }
 
@@ -485,7 +485,7 @@ impl Resolver {
         db: &dyn DefDatabase,
         path: &ModPath,
         expected_macro_kind: Option<MacroSubNs>,
-    ) -> Option<(MacroId, Option<ImportId>)> {
+    ) -> Option<(MacroId, Option<ImportOrGlob>)> {
         let (item_map, module) = self.item_scope();
         item_map
             .resolve_path(db, module, path, BuiltinShadowMode::Other, expected_macro_kind)
@@ -1014,7 +1014,7 @@ impl ModuleItemMap {
     }
 }
 
-fn to_value_ns(per_ns: PerNs) -> Option<(ValueNs, Option<ImportId>)> {
+fn to_value_ns(per_ns: PerNs) -> Option<(ValueNs, Option<ImportOrGlob>)> {
     let (def, import) = per_ns.take_values_import()?;
     let res = match def {
         ModuleDefId::FunctionId(it) => ValueNs::FunctionId(it),
diff --git a/crates/hir-expand/src/mod_path.rs b/crates/hir-expand/src/mod_path.rs
index f0cf7ebf47..89eae862bd 100644
--- a/crates/hir-expand/src/mod_path.rs
+++ b/crates/hir-expand/src/mod_path.rs
@@ -23,6 +23,15 @@ pub struct ModPath {
     segments: SmallVec<[Name; 1]>,
 }
 
+#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub struct UnescapedModPath<'a>(&'a ModPath);
+
+impl<'a> UnescapedModPath<'a> {
+    pub fn display(&'a self, db: &'a dyn crate::db::ExpandDatabase) -> impl fmt::Display + 'a {
+        UnescapedDisplay { db, path: self }
+    }
+}
+
 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
 pub enum PathKind {
     Plain,
@@ -126,11 +135,9 @@ impl ModPath {
             _ => None,
         }
     }
-    pub fn display_verbatim<'a>(
-        &'a self,
-        db: &'a dyn crate::db::ExpandDatabase,
-    ) -> impl fmt::Display + 'a {
-        Display { db, path: self, edition: None }
+
+    pub fn unescaped(&self) -> UnescapedModPath<'_> {
+        UnescapedModPath(self)
     }
 
     pub fn display<'a>(
@@ -138,7 +145,7 @@ impl ModPath {
         db: &'a dyn crate::db::ExpandDatabase,
         edition: Edition,
     ) -> impl fmt::Display + 'a {
-        Display { db, path: self, edition: Some(edition) }
+        Display { db, path: self, edition }
     }
 }
 
@@ -151,12 +158,23 @@ impl Extend<Name> for ModPath {
 struct Display<'a> {
     db: &'a dyn ExpandDatabase,
     path: &'a ModPath,
-    edition: Option<Edition>,
+    edition: Edition,
 }
 
 impl fmt::Display for Display<'_> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        display_fmt_path(self.db, self.path, f, self.edition)
+        display_fmt_path(self.db, self.path, f, Escape::IfNeeded(self.edition))
+    }
+}
+
+struct UnescapedDisplay<'a> {
+    db: &'a dyn ExpandDatabase,
+    path: &'a UnescapedModPath<'a>,
+}
+
+impl fmt::Display for UnescapedDisplay<'_> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        display_fmt_path(self.db, self.path.0, f, Escape::No)
     }
 }
 
@@ -166,11 +184,16 @@ impl From<Name> for ModPath {
     }
 }
 
+enum Escape {
+    No,
+    IfNeeded(Edition),
+}
+
 fn display_fmt_path(
     db: &dyn ExpandDatabase,
     path: &ModPath,
     f: &mut fmt::Formatter<'_>,
-    edition: Option<Edition>,
+    escaped: Escape,
 ) -> fmt::Result {
     let mut first_segment = true;
     let mut add_segment = |s| -> fmt::Result {
@@ -198,10 +221,10 @@ fn display_fmt_path(
             f.write_str("::")?;
         }
         first_segment = false;
-        match edition {
-            Some(edition) => segment.display(db, edition).fmt(f)?,
-            None => fmt::Display::fmt(segment.as_str(), f)?,
-        };
+        match escaped {
+            Escape::IfNeeded(edition) => segment.display(db, edition).fmt(f)?,
+            Escape::No => segment.unescaped().display(db).fmt(f)?,
+        }
     }
     Ok(())
 }
diff --git a/crates/hir-expand/src/name.rs b/crates/hir-expand/src/name.rs
index 848870c3a3..9cfa3b4b32 100644
--- a/crates/hir-expand/src/name.rs
+++ b/crates/hir-expand/src/name.rs
@@ -4,8 +4,8 @@ use std::fmt;
 
 use intern::{sym, Symbol};
 use span::{Edition, SyntaxContextId};
+use syntax::ast;
 use syntax::utils::is_raw_identifier;
-use syntax::{ast, format_smolstr};
 
 /// `Name` is a wrapper around string, which is used in hir for both references
 /// and declarations. In theory, names should also carry hygiene info, but we are
@@ -69,8 +69,27 @@ impl PartialEq<Name> for &Symbol {
     }
 }
 
+/// Wrapper of `Name` to print the name without "r#" even when it is a raw identifier.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct UnescapedName<'a>(&'a Name);
+
+impl<'a> UnescapedName<'a> {
+    pub fn display(self, db: &dyn crate::db::ExpandDatabase) -> impl fmt::Display + 'a {
+        _ = db;
+        UnescapedDisplay { name: self }
+    }
+    #[doc(hidden)]
+    pub fn display_no_db(self) -> impl fmt::Display + 'a {
+        UnescapedDisplay { name: self }
+    }
+}
+
 impl Name {
+    /// Note: this is private to make creating name from random string hard.
+    /// Hopefully, this should allow us to integrate hygiene cleaner in the
+    /// future, and to switch to interned representation of names.
     fn new_text(text: &str) -> Name {
+        debug_assert!(!text.starts_with("r#"));
         Name { symbol: Symbol::intern(text), ctx: () }
     }
 
@@ -80,15 +99,12 @@ impl Name {
         // Can't do that for all `SyntaxContextId`s because it breaks Salsa.
         ctx.remove_root_edition();
         _ = ctx;
-        match text.strip_prefix("r#") {
-            Some(text) => Self::new_text(text),
-            None => Self::new_text(text),
-        }
+        Self::new_text(text)
     }
 
     pub fn new_root(text: &str) -> Name {
         // The edition doesn't matter for hygiene.
-        Self::new(text, SyntaxContextId::root(Edition::Edition2015))
+        Self::new(text.trim_start_matches("r#"), SyntaxContextId::root(Edition::Edition2015))
     }
 
     pub fn new_tuple_field(idx: usize) -> Name {
@@ -115,22 +131,12 @@ impl Name {
     }
 
     pub fn new_lifetime(lt: &ast::Lifetime) -> Name {
-        let text = lt.text();
-        match text.strip_prefix("'r#") {
-            Some(text) => Self::new_text(&format_smolstr!("'{text}")),
-            None => Self::new_text(text.as_str()),
-        }
+        Self::new_text(lt.text().as_str().trim_start_matches("r#"))
     }
 
-    pub fn new_symbol(symbol: Symbol, ctx: SyntaxContextId) -> Self {
-        debug_assert!(!symbol.as_str().starts_with("r#"));
-        _ = ctx;
-        Self { symbol, ctx: () }
-    }
-
-    // FIXME: This needs to go once we have hygiene
-    pub fn new_symbol_root(sym: Symbol) -> Self {
-        Self::new_symbol(sym, SyntaxContextId::root(Edition::Edition2015))
+    /// Resolve a name from the text of token.
+    fn resolve(raw_text: &str) -> Name {
+        Name::new_text(raw_text.trim_start_matches("r#"))
     }
 
     /// A fake name for things missing in the source code.
@@ -167,19 +173,22 @@ impl Name {
         self.symbol.as_str().parse().ok()
     }
 
-    /// Whether this name needs to be escaped in the given edition via `r#`.
-    pub fn needs_escape(&self, edition: Edition) -> bool {
-        is_raw_identifier(self.symbol.as_str(), edition)
-    }
-
     /// Returns the text this name represents if it isn't a tuple field.
     ///
     /// Do not use this for user-facing text, use `display` instead to handle editions properly.
-    // FIXME: This should take a database argument to hide the interning
     pub fn as_str(&self) -> &str {
         self.symbol.as_str()
     }
 
+    // FIXME: Remove this
+    pub fn unescaped(&self) -> UnescapedName<'_> {
+        UnescapedName(self)
+    }
+
+    pub fn needs_escape(&self, edition: Edition) -> bool {
+        is_raw_identifier(self.symbol.as_str(), edition)
+    }
+
     pub fn display<'a>(
         &'a self,
         db: &dyn crate::db::ExpandDatabase,
@@ -189,7 +198,7 @@ impl Name {
         self.display_no_db(edition)
     }
 
-    // FIXME: Remove this in favor of `display`, see fixme on `as_str`
+    // FIXME: Remove this
     #[doc(hidden)]
     pub fn display_no_db(&self, edition: Edition) -> impl fmt::Display + '_ {
         Display { name: self, needs_escaping: is_raw_identifier(self.symbol.as_str(), edition) }
@@ -198,6 +207,24 @@ impl Name {
     pub fn symbol(&self) -> &Symbol {
         &self.symbol
     }
+
+    pub fn new_symbol(symbol: Symbol, ctx: SyntaxContextId) -> Self {
+        debug_assert!(!symbol.as_str().starts_with("r#"));
+        _ = ctx;
+        Self { symbol, ctx: () }
+    }
+
+    // FIXME: This needs to go once we have hygiene
+    pub fn new_symbol_root(sym: Symbol) -> Self {
+        debug_assert!(!sym.as_str().starts_with("r#"));
+        Self { symbol: sym, ctx: () }
+    }
+
+    // FIXME: Remove this
+    #[inline]
+    pub fn eq_ident(&self, ident: &str) -> bool {
+        self.as_str() == ident.trim_start_matches("r#")
+    }
 }
 
 struct Display<'a> {
@@ -214,6 +241,17 @@ impl fmt::Display for Display<'_> {
     }
 }
 
+struct UnescapedDisplay<'a> {
+    name: UnescapedName<'a>,
+}
+
+impl fmt::Display for UnescapedDisplay<'_> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let symbol = self.name.0.symbol.as_str();
+        fmt::Display::fmt(symbol, f)
+    }
+}
+
 pub trait AsName {
     fn as_name(&self) -> Name;
 }
@@ -222,14 +260,14 @@ impl AsName for ast::NameRef {
     fn as_name(&self) -> Name {
         match self.as_tuple_field() {
             Some(idx) => Name::new_tuple_field(idx),
-            None => Name::new_root(&self.text()),
+            None => Name::resolve(&self.text()),
         }
     }
 }
 
 impl AsName for ast::Name {
     fn as_name(&self) -> Name {
-        Name::new_root(&self.text())
+        Name::resolve(&self.text())
     }
 }
 
@@ -244,7 +282,7 @@ impl AsName for ast::NameOrNameRef {
 
 impl<Span> AsName for tt::Ident<Span> {
     fn as_name(&self) -> Name {
-        Name::new_root(self.sym.as_str())
+        Name::resolve(self.sym.as_str())
     }
 }
 
@@ -262,6 +300,6 @@ impl AsName for ast::FieldKind {
 
 impl AsName for base_db::Dependency {
     fn as_name(&self) -> Name {
-        Name::new_root(&self.name)
+        Name::new_text(&self.name)
     }
 }
diff --git a/crates/hir-ty/src/autoderef.rs b/crates/hir-ty/src/autoderef.rs
index 2c7076da11..2b5342314a 100644
--- a/crates/hir-ty/src/autoderef.rs
+++ b/crates/hir-ty/src/autoderef.rs
@@ -17,7 +17,7 @@ use crate::{
     TraitEnvironment, Ty, TyBuilder, TyKind,
 };
 
-static AUTODEREF_RECURSION_LIMIT: Limit = Limit::new(20);
+static AUTODEREF_RECURSION_LIMIT: Limit = Limit::new(10);
 
 #[derive(Debug)]
 pub(crate) enum AutoderefKind {
@@ -49,7 +49,7 @@ pub fn autoderef(
         // If the deref chain contains a cycle (e.g. `A` derefs to `B` and `B` derefs to `A`), we
         // would revisit some already visited types. Stop here to avoid duplication.
         //
-        // XXX: The recursion limit for `Autoderef` is currently 20, so `Vec::contains()` shouldn't
+        // XXX: The recursion limit for `Autoderef` is currently 10, so `Vec::contains()` shouldn't
         // be too expensive. Replace this duplicate check with `FxHashSet` if it proves to be more
         // performant.
         if v.contains(&resolved) {
diff --git a/crates/hir-ty/src/diagnostics/decl_check.rs b/crates/hir-ty/src/diagnostics/decl_check.rs
index 774991560e..4991d173b9 100644
--- a/crates/hir-ty/src/diagnostics/decl_check.rs
+++ b/crates/hir-ty/src/diagnostics/decl_check.rs
@@ -231,7 +231,8 @@ impl<'a> DeclValidator<'a> {
             .filter_map(|(pat_id, pat)| match pat {
                 Pat::Bind { id, .. } => {
                     let bind_name = &body.bindings[*id].name;
-                    let mut suggested_text = to_lower_snake_case(bind_name.as_str())?;
+                    let mut suggested_text =
+                        to_lower_snake_case(&bind_name.unescaped().display_no_db().to_smolstr())?;
                     if is_raw_identifier(&suggested_text, edition) {
                         suggested_text.insert_str(0, "r#");
                     }
diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs
index 9283c46d0f..2523aba538 100644
--- a/crates/hir-ty/src/infer/closure.rs
+++ b/crates/hir-ty/src/infer/closure.rs
@@ -277,7 +277,7 @@ impl CapturedItem {
     /// Converts the place to a name that can be inserted into source code.
     pub fn place_to_name(&self, owner: DefWithBodyId, db: &dyn HirDatabase) -> String {
         let body = db.body(owner);
-        let mut result = body[self.place.local].name.as_str().to_owned();
+        let mut result = body[self.place.local].name.unescaped().display(db.upcast()).to_string();
         for proj in &self.place.projections {
             match proj {
                 ProjectionElem::Deref => {}
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index 09470bed9c..708db2c08d 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -1483,8 +1483,6 @@ impl<'db> SemanticsImpl<'db> {
         self.analyze(try_expr.syntax())?.resolve_try_expr(self.db, try_expr)
     }
 
-    // This does not resolve the method call to the correct trait impl!
-    // We should probably fix that.
     pub fn resolve_method_call_as_callable(&self, call: &ast::MethodCallExpr) -> Option<Callable> {
         self.analyze(call.syntax())?.resolve_method_call_as_callable(self.db, call)
     }
diff --git a/crates/hir/src/symbols.rs b/crates/hir/src/symbols.rs
index a6b8ed70c3..f379a2d4d6 100644
--- a/crates/hir/src/symbols.rs
+++ b/crates/hir/src/symbols.rs
@@ -3,7 +3,7 @@
 use either::Either;
 use hir_def::{
     db::DefDatabase,
-    item_scope::{ImportId, ImportOrExternCrate},
+    item_scope::{ImportId, ImportOrExternCrate, ImportOrGlob},
     per_ns::Item,
     src::{HasChildSource, HasSource},
     visibility::{Visibility, VisibilityExplicitness},
@@ -55,9 +55,10 @@ impl DeclarationLocation {
 }
 
 /// Represents an outstanding module that the symbol collector must collect symbols from.
+#[derive(Debug)]
 struct SymbolCollectorWork {
     module_id: ModuleId,
-    parent: Option<DefWithBodyId>,
+    parent: Option<Name>,
 }
 
 pub struct SymbolCollector<'a> {
@@ -81,7 +82,15 @@ impl<'a> SymbolCollector<'a> {
         }
     }
 
+    pub fn new_module(db: &dyn HirDatabase, module: Module) -> Box<[FileSymbol]> {
+        let mut symbol_collector = SymbolCollector::new(db);
+        symbol_collector.collect(module);
+        symbol_collector.finish()
+    }
+
     pub fn collect(&mut self, module: Module) {
+        let _p = tracing::info_span!("SymbolCollector::collect", ?module).entered();
+        tracing::info!(?module, "SymbolCollector::collect",);
         self.edition = module.krate().edition(self.db);
 
         // The initial work is the root module we're collecting, additional work will
@@ -97,16 +106,12 @@ impl<'a> SymbolCollector<'a> {
         self.symbols.into_iter().collect()
     }
 
-    pub fn collect_module(db: &dyn HirDatabase, module: Module) -> Box<[FileSymbol]> {
-        let mut symbol_collector = SymbolCollector::new(db);
-        symbol_collector.collect(module);
-        symbol_collector.finish()
-    }
-
     fn do_work(&mut self, work: SymbolCollectorWork) {
+        let _p = tracing::info_span!("SymbolCollector::do_work", ?work).entered();
+        tracing::info!(?work, "SymbolCollector::do_work");
         self.db.unwind_if_cancelled();
 
-        let parent_name = work.parent.and_then(|id| self.def_with_body_id_name(id));
+        let parent_name = work.parent.map(|name| name.as_str().to_smolstr());
         self.with_container_name(parent_name, |s| s.collect_from_module(work.module_id));
     }
 
@@ -116,18 +121,18 @@ impl<'a> SymbolCollector<'a> {
                 ModuleDefId::ModuleId(id) => this.push_module(id, name),
                 ModuleDefId::FunctionId(id) => {
                     this.push_decl(id, name, false);
-                    this.collect_from_body(id);
+                    this.collect_from_body(id, Some(name.clone()));
                 }
                 ModuleDefId::AdtId(AdtId::StructId(id)) => this.push_decl(id, name, false),
                 ModuleDefId::AdtId(AdtId::EnumId(id)) => this.push_decl(id, name, false),
                 ModuleDefId::AdtId(AdtId::UnionId(id)) => this.push_decl(id, name, false),
                 ModuleDefId::ConstId(id) => {
                     this.push_decl(id, name, false);
-                    this.collect_from_body(id);
+                    this.collect_from_body(id, Some(name.clone()));
                 }
                 ModuleDefId::StaticId(id) => {
                     this.push_decl(id, name, false);
-                    this.collect_from_body(id);
+                    this.collect_from_body(id, Some(name.clone()));
                 }
                 ModuleDefId::TraitId(id) => {
                     this.push_decl(id, name, false);
@@ -235,6 +240,7 @@ impl<'a> SymbolCollector<'a> {
                 if is_explicit_import(vis) {
                     match i {
                         ImportOrExternCrate::Import(i) => push_import(self, i, name, def),
+                        ImportOrExternCrate::Glob(_) => (),
                         ImportOrExternCrate::ExternCrate(i) => {
                             push_extern_crate(self, i, name, def)
                         }
@@ -249,7 +255,10 @@ impl<'a> SymbolCollector<'a> {
         for (name, Item { def, vis, import }) in scope.macros() {
             if let Some(i) = import {
                 if is_explicit_import(vis) {
-                    push_import(self, i, name, def.into());
+                    match i {
+                        ImportOrGlob::Import(i) => push_import(self, i, name, def.into()),
+                        ImportOrGlob::Glob(_) => (),
+                    }
                 }
                 continue;
             }
@@ -260,7 +269,10 @@ impl<'a> SymbolCollector<'a> {
         for (name, Item { def, vis, import }) in scope.values() {
             if let Some(i) = import {
                 if is_explicit_import(vis) {
-                    push_import(self, i, name, def);
+                    match i {
+                        ImportOrGlob::Import(i) => push_import(self, i, name, def),
+                        ImportOrGlob::Glob(_) => (),
+                    }
                 }
                 continue;
             }
@@ -269,7 +281,7 @@ impl<'a> SymbolCollector<'a> {
         }
 
         for const_id in scope.unnamed_consts() {
-            self.collect_from_body(const_id);
+            self.collect_from_body(const_id, None);
         }
 
         for (name, id) in scope.legacy_macros() {
@@ -285,7 +297,7 @@ impl<'a> SymbolCollector<'a> {
         }
     }
 
-    fn collect_from_body(&mut self, body_id: impl Into<DefWithBodyId>) {
+    fn collect_from_body(&mut self, body_id: impl Into<DefWithBodyId>, name: Option<Name>) {
         let body_id = body_id.into();
         let body = self.db.body(body_id);
 
@@ -294,7 +306,7 @@ impl<'a> SymbolCollector<'a> {
             for (id, _) in def_map.modules() {
                 self.work.push(SymbolCollectorWork {
                     module_id: def_map.module_id(id),
-                    parent: Some(body_id),
+                    parent: name.clone(),
                 });
             }
         }
@@ -333,24 +345,6 @@ impl<'a> SymbolCollector<'a> {
         }
     }
 
-    fn def_with_body_id_name(&self, body_id: DefWithBodyId) -> Option<SmolStr> {
-        match body_id {
-            DefWithBodyId::FunctionId(id) => {
-                Some(self.db.function_data(id).name.display_no_db(self.edition).to_smolstr())
-            }
-            DefWithBodyId::StaticId(id) => {
-                Some(self.db.static_data(id).name.display_no_db(self.edition).to_smolstr())
-            }
-            DefWithBodyId::ConstId(id) => {
-                Some(self.db.const_data(id).name.as_ref()?.display_no_db(self.edition).to_smolstr())
-            }
-            DefWithBodyId::VariantId(id) => {
-                Some(self.db.enum_variant_data(id).name.display_no_db(self.edition).to_smolstr())
-            }
-            DefWithBodyId::InTypeConstId(_) => Some("in type const".into()),
-        }
-    }
-
     fn push_assoc_item(&mut self, assoc_item_id: AssocItemId, name: &Name) {
         match assoc_item_id {
             AssocItemId::FunctionId(id) => self.push_decl(id, name, true),
diff --git a/crates/ide-assists/src/handlers/convert_bool_then.rs b/crates/ide-assists/src/handlers/convert_bool_then.rs
index eb784cd122..a5c5b08d5b 100644
--- a/crates/ide-assists/src/handlers/convert_bool_then.rs
+++ b/crates/ide-assists/src/handlers/convert_bool_then.rs
@@ -159,7 +159,7 @@ pub(crate) fn convert_bool_then_to_if(acc: &mut Assists, ctx: &AssistContext<'_>
     };
     // Verify this is `bool::then` that is being called.
     let func = ctx.sema.resolve_method_call(&mcall)?;
-    if func.name(ctx.sema.db) != sym::then {
+    if !func.name(ctx.sema.db).eq_ident("then") {
         return None;
     }
     let assoc = func.as_assoc_item(ctx.sema.db)?;
diff --git a/crates/ide-assists/src/handlers/convert_closure_to_fn.rs b/crates/ide-assists/src/handlers/convert_closure_to_fn.rs
index d34cf895cd..bb04a43cf9 100644
--- a/crates/ide-assists/src/handlers/convert_closure_to_fn.rs
+++ b/crates/ide-assists/src/handlers/convert_closure_to_fn.rs
@@ -343,9 +343,11 @@ fn compute_closure_type_params(
     let mut mentioned_names = mentioned_generic_params
         .iter()
         .filter_map(|param| match param {
-            hir::GenericParam::TypeParam(param) => Some(param.name(ctx.db()).as_str().to_smolstr()),
+            hir::GenericParam::TypeParam(param) => {
+                Some(param.name(ctx.db()).unescaped().display(ctx.db()).to_smolstr())
+            }
             hir::GenericParam::ConstParam(param) => {
-                Some(param.name(ctx.db()).as_str().to_smolstr())
+                Some(param.name(ctx.db()).unescaped().display(ctx.db()).to_smolstr())
             }
             hir::GenericParam::LifetimeParam(_) => None,
         })
@@ -388,7 +390,7 @@ fn compute_closure_type_params(
             let has_name = syntax
                 .descendants()
                 .filter_map(ast::NameOrNameRef::cast)
-                .any(|name| mentioned_names.contains(name.text().trim_start_matches("r#")));
+                .any(|name| mentioned_names.contains(&*name.text()));
             let mut has_new_params = false;
             if has_name {
                 syntax
diff --git a/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs b/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs
index d4f2ea3bd9..615b5d3f98 100644
--- a/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs
+++ b/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs
@@ -170,7 +170,7 @@ fn existing_definition(db: &RootDatabase, variant_name: &ast::Name, variant: &Va
             ),
             _ => false,
         })
-        .any(|(name, _)| name.as_str() == variant_name.text().trim_start_matches("r#"))
+        .any(|(name, _)| name.eq_ident(variant_name.text().as_str()))
 }
 
 fn extract_generic_params(
diff --git a/crates/ide-assists/src/handlers/fix_visibility.rs b/crates/ide-assists/src/handlers/fix_visibility.rs
index 47e4a68293..7a92d8911b 100644
--- a/crates/ide-assists/src/handlers/fix_visibility.rs
+++ b/crates/ide-assists/src/handlers/fix_visibility.rs
@@ -48,7 +48,7 @@ fn add_vis_to_referenced_module_def(acc: &mut Assists, ctx: &AssistContext<'_>)
     let (_, def) = module
         .scope(ctx.db(), None)
         .into_iter()
-        .find(|(name, _)| name.as_str() == name_ref.text().trim_start_matches("r#"))?;
+        .find(|(name, _)| name.eq_ident(name_ref.text().as_str()))?;
     let ScopeDef::ModuleDef(def) = def else {
         return None;
     };
diff --git a/crates/ide-assists/src/handlers/move_from_mod_rs.rs b/crates/ide-assists/src/handlers/move_from_mod_rs.rs
index 10915f8aaf..8a7a06b380 100644
--- a/crates/ide-assists/src/handlers/move_from_mod_rs.rs
+++ b/crates/ide-assists/src/handlers/move_from_mod_rs.rs
@@ -2,7 +2,7 @@ use ide_db::{
     assists::{AssistId, AssistKind},
     base_db::AnchoredPathBuf,
 };
-use syntax::{ast, AstNode, ToSmolStr};
+use syntax::{ast, AstNode};
 
 use crate::{
     assist_context::{AssistContext, Assists},
@@ -39,7 +39,7 @@ pub(crate) fn move_from_mod_rs(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
     }
 
     let target = source_file.syntax().text_range();
-    let module_name = module.name(ctx.db())?.as_str().to_smolstr();
+    let module_name = module.name(ctx.db())?.unescaped().display(ctx.db()).to_string();
     let path = format!("../{module_name}.rs");
     let dst = AnchoredPathBuf { anchor: ctx.file_id().into(), path };
     acc.add(
diff --git a/crates/ide-assists/src/handlers/move_module_to_file.rs b/crates/ide-assists/src/handlers/move_module_to_file.rs
index bbf18e2194..9692b70592 100644
--- a/crates/ide-assists/src/handlers/move_module_to_file.rs
+++ b/crates/ide-assists/src/handlers/move_module_to_file.rs
@@ -61,7 +61,7 @@ pub(crate) fn move_module_to_file(acc: &mut Assists, ctx: &AssistContext<'_>) ->
                                 .string_value_unescape()
                                 .is_none() =>
                     {
-                        format_to!(buf, "{}/", name.as_str())
+                        format_to!(buf, "{}/", name.unescaped().display(db))
                     }
                     _ => (),
                 }
diff --git a/crates/ide-assists/src/handlers/move_to_mod_rs.rs b/crates/ide-assists/src/handlers/move_to_mod_rs.rs
index 7b38c795dc..2925e2334b 100644
--- a/crates/ide-assists/src/handlers/move_to_mod_rs.rs
+++ b/crates/ide-assists/src/handlers/move_to_mod_rs.rs
@@ -2,7 +2,7 @@ use ide_db::{
     assists::{AssistId, AssistKind},
     base_db::AnchoredPathBuf,
 };
-use syntax::{ast, AstNode, ToSmolStr};
+use syntax::{ast, AstNode};
 
 use crate::{
     assist_context::{AssistContext, Assists},
@@ -39,7 +39,7 @@ pub(crate) fn move_to_mod_rs(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
     }
 
     let target = source_file.syntax().text_range();
-    let module_name = module.name(ctx.db())?.as_str().to_smolstr();
+    let module_name = module.name(ctx.db())?.unescaped().display(ctx.db()).to_string();
     let path = format!("./{module_name}/mod.rs");
     let dst = AnchoredPathBuf { anchor: ctx.file_id().into(), path };
     acc.add(
diff --git a/crates/ide-assists/src/handlers/qualify_path.rs b/crates/ide-assists/src/handlers/qualify_path.rs
index 2a8465f634..849b8a42c6 100644
--- a/crates/ide-assists/src/handlers/qualify_path.rs
+++ b/crates/ide-assists/src/handlers/qualify_path.rs
@@ -208,7 +208,7 @@ fn find_trait_method(
     if let Some(hir::AssocItem::Function(method)) =
         trait_.items(db).into_iter().find(|item: &hir::AssocItem| {
             item.name(db)
-                .map(|name| name.as_str() == trait_method_name.text().trim_start_matches("r#"))
+                .map(|name| name.eq_ident(trait_method_name.text().as_str()))
                 .unwrap_or(false)
         })
     {
diff --git a/crates/ide-assists/src/handlers/reorder_fields.rs b/crates/ide-assists/src/handlers/reorder_fields.rs
index a79a82be45..972303c2a0 100644
--- a/crates/ide-assists/src/handlers/reorder_fields.rs
+++ b/crates/ide-assists/src/handlers/reorder_fields.rs
@@ -110,7 +110,7 @@ fn compute_fields_ranks(
         .fields(ctx.db())
         .into_iter()
         .enumerate()
-        .map(|(idx, field)| (field.name(ctx.db()).as_str().to_owned(), idx))
+        .map(|(idx, field)| (field.name(ctx.db()).unescaped().display(ctx.db()).to_string(), idx))
         .collect();
 
     Some(res)
diff --git a/crates/ide-assists/src/handlers/reorder_impl_items.rs b/crates/ide-assists/src/handlers/reorder_impl_items.rs
index c3404173ea..eb1d538f87 100644
--- a/crates/ide-assists/src/handlers/reorder_impl_items.rs
+++ b/crates/ide-assists/src/handlers/reorder_impl_items.rs
@@ -122,7 +122,7 @@ fn compute_item_ranks(
             .iter()
             .flat_map(|i| i.name(ctx.db()))
             .enumerate()
-            .map(|(idx, name)| (name.as_str().to_owned(), idx))
+            .map(|(idx, name)| (name.unescaped().display(ctx.db()).to_string(), idx))
             .collect(),
     )
 }
diff --git a/crates/ide-completion/src/completions/flyimport.rs b/crates/ide-completion/src/completions/flyimport.rs
index 435b88de4a..73313eeaa6 100644
--- a/crates/ide-completion/src/completions/flyimport.rs
+++ b/crates/ide-completion/src/completions/flyimport.rs
@@ -5,7 +5,7 @@ use ide_db::imports::{
     insert_use::ImportScope,
 };
 use itertools::Itertools;
-use syntax::{ast, AstNode, SyntaxNode};
+use syntax::{ast, AstNode, SyntaxNode, ToSmolStr};
 
 use crate::{
     config::AutoImportExclusionType,
@@ -444,7 +444,7 @@ fn compute_fuzzy_completion_order_key(
     cov_mark::hit!(certain_fuzzy_order_test);
     let import_name = match proposed_mod_path.segments().last() {
         // FIXME: nasty alloc, this is a hot path!
-        Some(name) => name.as_str().to_ascii_lowercase(),
+        Some(name) => name.unescaped().display_no_db().to_smolstr().to_ascii_lowercase(),
         None => return usize::MAX,
     };
     match import_name.match_indices(user_input_lowercased).next() {
diff --git a/crates/ide-completion/src/completions/item_list/trait_impl.rs b/crates/ide-completion/src/completions/item_list/trait_impl.rs
index 5f0288ae95..18629529b7 100644
--- a/crates/ide-completion/src/completions/item_list/trait_impl.rs
+++ b/crates/ide-completion/src/completions/item_list/trait_impl.rs
@@ -362,7 +362,7 @@ fn add_type_alias_impl(
     type_alias: hir::TypeAlias,
     impl_def: hir::Impl,
 ) {
-    let alias_name = type_alias.name(ctx.db).as_str().to_smolstr();
+    let alias_name = type_alias.name(ctx.db).unescaped().display(ctx.db).to_smolstr();
 
     let label = format_smolstr!("type {alias_name} =");
 
diff --git a/crates/ide-completion/src/completions/mod_.rs b/crates/ide-completion/src/completions/mod_.rs
index cca6a22f29..bafe329420 100644
--- a/crates/ide-completion/src/completions/mod_.rs
+++ b/crates/ide-completion/src/completions/mod_.rs
@@ -7,7 +7,7 @@ use ide_db::{
     base_db::{SourceRootDatabase, VfsPath},
     FxHashSet, RootDatabase, SymbolKind,
 };
-use syntax::{ast, AstNode, SyntaxKind};
+use syntax::{ast, AstNode, SyntaxKind, ToSmolStr};
 
 use crate::{context::CompletionContext, CompletionItem, Completions};
 
@@ -140,7 +140,9 @@ fn directory_to_look_for_submodules(
     module_chain_to_containing_module_file(module, db)
         .into_iter()
         .filter_map(|module| module.name(db))
-        .try_fold(base_directory, |path, name| path.join(name.as_str()))
+        .try_fold(base_directory, |path, name| {
+            path.join(&name.unescaped().display_no_db().to_smolstr())
+        })
 }
 
 fn module_chain_to_containing_module_file(
diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs
index f5a50ae819..562f60dbe2 100644
--- a/crates/ide-completion/src/context/analysis.rs
+++ b/crates/ide-completion/src/context/analysis.rs
@@ -1595,11 +1595,11 @@ fn pattern_context_for(
                                         }).map(|enum_| enum_.variants(sema.db))
                                     })
                                 }).map(|variants| variants.iter().filter_map(|variant| {
-                                        let variant_name = variant.name(sema.db);
+                                        let variant_name = variant.name(sema.db).unescaped().display(sema.db).to_string();
 
                                         let variant_already_present = match_arm_list.arms().any(|arm| {
                                             arm.pat().and_then(|pat| {
-                                                let pat_already_present = pat.syntax().to_string().contains(variant_name.as_str());
+                                                let pat_already_present = pat.syntax().to_string().contains(&variant_name);
                                                 pat_already_present.then_some(pat_already_present)
                                             }).is_some()
                                         });
diff --git a/crates/ide-completion/src/item.rs b/crates/ide-completion/src/item.rs
index b0a096b64a..dc2f9a7680 100644
--- a/crates/ide-completion/src/item.rs
+++ b/crates/ide-completion/src/item.rs
@@ -181,8 +181,6 @@ pub struct CompletionRelevance {
     pub postfix_match: Option<CompletionRelevancePostfixMatch>,
     /// This is set for items that are function (associated or method)
     pub function: Option<CompletionRelevanceFn>,
-    /// true when there is an `await.method()` or `iter().method()` completion.
-    pub is_skipping_completion: bool,
 }
 #[derive(Debug, Clone, Copy, Eq, PartialEq)]
 pub struct CompletionRelevanceTraitInfo {
@@ -271,7 +269,6 @@ impl CompletionRelevance {
             postfix_match,
             trait_,
             function,
-            is_skipping_completion,
         } = self;
 
         // only applicable for completions within use items
@@ -299,12 +296,6 @@ impl CompletionRelevance {
                 score -= 5;
             }
         }
-
-        // Lower rank for completions that skip `await` and `iter()`.
-        if is_skipping_completion {
-            score -= 7;
-        }
-
         // lower rank for items that need an import
         if requires_import {
             score -= 1;
diff --git a/crates/ide-completion/src/render.rs b/crates/ide-completion/src/render.rs
index 1b7adf1adb..61e8114d38 100644
--- a/crates/ide-completion/src/render.rs
+++ b/crates/ide-completion/src/render.rs
@@ -130,8 +130,10 @@ pub(crate) fn render_field(
     let db = ctx.db();
     let is_deprecated = ctx.is_deprecated(field);
     let name = field.name(db);
-    let (name, escaped_name) =
-        (name.as_str().to_smolstr(), name.display_no_db(ctx.completion.edition).to_smolstr());
+    let (name, escaped_name) = (
+        name.unescaped().display(db).to_smolstr(),
+        name.display_no_db(ctx.completion.edition).to_smolstr(),
+    );
     let mut item = CompletionItem::new(
         SymbolKind::Field,
         ctx.source_range(),
@@ -140,8 +142,7 @@ pub(crate) fn render_field(
     );
     item.set_relevance(CompletionRelevance {
         type_match: compute_type_match(ctx.completion, ty),
-        exact_name_match: compute_exact_name_match(ctx.completion, &name),
-        is_skipping_completion: receiver.is_some(),
+        exact_name_match: compute_exact_name_match(ctx.completion, name.as_str()),
         ..CompletionRelevance::default()
     });
     item.detail(ty.display(db, ctx.completion.edition).to_string())
@@ -214,10 +215,6 @@ pub(crate) fn render_tuple_field(
     );
     item.detail(ty.display(ctx.db(), ctx.completion.edition).to_string())
         .lookup_by(field.to_string());
-    item.set_relevance(CompletionRelevance {
-        is_skipping_completion: receiver.is_some(),
-        ..ctx.completion_relevance()
-    });
     item.build(ctx.db())
 }
 
@@ -515,7 +512,7 @@ fn render_resolution_simple_(
     let mut item = CompletionItem::new(
         kind,
         ctx.source_range(),
-        local_name.as_str().to_smolstr(),
+        local_name.unescaped().display(db).to_smolstr(),
         ctx.completion.edition,
     );
     item.set_relevance(ctx.completion_relevance())
@@ -1338,7 +1335,6 @@ fn main() { let _: m::Spam = S$0 }
                             is_private_editable: false,
                             postfix_match: None,
                             function: None,
-                            is_skipping_completion: false,
                         },
                         trigger_call_info: true,
                     },
@@ -1368,7 +1364,6 @@ fn main() { let _: m::Spam = S$0 }
                             is_private_editable: false,
                             postfix_match: None,
                             function: None,
-                            is_skipping_completion: false,
                         },
                         trigger_call_info: true,
                     },
@@ -1458,7 +1453,6 @@ fn foo() { A { the$0 } }
                             is_private_editable: false,
                             postfix_match: None,
                             function: None,
-                            is_skipping_completion: false,
                         },
                     },
                 ]
@@ -1517,7 +1511,6 @@ impl S {
                                     return_type: Other,
                                 },
                             ),
-                            is_skipping_completion: false,
                         },
                     },
                     CompletionItem {
@@ -1660,7 +1653,6 @@ fn foo(s: S) { s.$0 }
                                     return_type: Other,
                                 },
                             ),
-                            is_skipping_completion: false,
                         },
                     },
                 ]
@@ -1872,7 +1864,6 @@ fn f() -> i32 {
                             is_private_editable: false,
                             postfix_match: None,
                             function: None,
-                            is_skipping_completion: false,
                         },
                     },
                 ]
@@ -2633,7 +2624,6 @@ fn foo(f: Foo) { let _: &u32 = f.b$0 }
                                     return_type: Other,
                                 },
                             ),
-                            is_skipping_completion: false,
                         },
                         ref_match: "&@107",
                     },
@@ -2719,7 +2709,6 @@ fn foo() {
                             is_private_editable: false,
                             postfix_match: None,
                             function: None,
-                            is_skipping_completion: false,
                         },
                     },
                 ]
@@ -2777,7 +2766,6 @@ fn main() {
                                     return_type: Other,
                                 },
                             ),
-                            is_skipping_completion: false,
                         },
                         ref_match: "&@92",
                     },
@@ -3152,7 +3140,6 @@ fn main() {
                             is_private_editable: false,
                             postfix_match: None,
                             function: None,
-                            is_skipping_completion: false,
                         },
                     },
                     CompletionItem {
@@ -3186,7 +3173,6 @@ fn main() {
                             is_private_editable: false,
                             postfix_match: None,
                             function: None,
-                            is_skipping_completion: false,
                         },
                     },
                 ]
diff --git a/crates/ide-completion/src/render/const_.rs b/crates/ide-completion/src/render/const_.rs
index e357ab24d2..415d87c623 100644
--- a/crates/ide-completion/src/render/const_.rs
+++ b/crates/ide-completion/src/render/const_.rs
@@ -14,8 +14,10 @@ pub(crate) fn render_const(ctx: RenderContext<'_>, const_: hir::Const) -> Option
 fn render(ctx: RenderContext<'_>, const_: hir::Const) -> Option<CompletionItem> {
     let db = ctx.db();
     let name = const_.name(db)?;
-    let (name, escaped_name) =
-        (name.as_str().to_smolstr(), name.display(db, ctx.completion.edition).to_smolstr());
+    let (name, escaped_name) = (
+        name.unescaped().display(db).to_smolstr(),
+        name.display(db, ctx.completion.edition).to_smolstr(),
+    );
     let detail = const_.display(db, ctx.completion.edition).to_string();
 
     let mut item =
diff --git a/crates/ide-completion/src/render/function.rs b/crates/ide-completion/src/render/function.rs
index c3354902c3..3b97d67169 100644
--- a/crates/ide-completion/src/render/function.rs
+++ b/crates/ide-completion/src/render/function.rs
@@ -59,10 +59,13 @@ fn render(
 
     let (call, escaped_call) = match &func_kind {
         FuncKind::Method(_, Some(receiver)) => (
-            format_smolstr!("{}.{}", receiver, name.as_str()),
+            format_smolstr!("{}.{}", receiver, name.unescaped().display(ctx.db())),
             format_smolstr!("{}.{}", receiver, name.display(ctx.db(), completion.edition)),
         ),
-        _ => (name.as_str().to_smolstr(), name.display(db, completion.edition).to_smolstr()),
+        _ => (
+            name.unescaped().display(db).to_smolstr(),
+            name.display(db, completion.edition).to_smolstr(),
+        ),
     };
     let has_self_param = func.self_param(db).is_some();
     let mut item = CompletionItem::new(
@@ -123,7 +126,6 @@ fn render(
         exact_name_match: compute_exact_name_match(completion, &call),
         function,
         trait_: trait_info,
-        is_skipping_completion: matches!(func_kind, FuncKind::Method(_, Some(_))),
         ..ctx.completion_relevance()
     });
 
@@ -149,7 +151,7 @@ fn render(
     item.set_documentation(ctx.docs(func))
         .set_deprecated(ctx.is_deprecated(func) || ctx.is_deprecated_assoc_item(func))
         .detail(detail)
-        .lookup_by(name.as_str().to_smolstr());
+        .lookup_by(name.unescaped().display(db).to_smolstr());
 
     if let Some((cap, (self_param, params))) = complete_call_parens {
         add_call_parens(
diff --git a/crates/ide-completion/src/render/literal.rs b/crates/ide-completion/src/render/literal.rs
index aab54ca5e0..c71356e530 100644
--- a/crates/ide-completion/src/render/literal.rs
+++ b/crates/ide-completion/src/render/literal.rs
@@ -75,7 +75,7 @@ fn render(
         None => (name.clone().into(), name.into(), false),
     };
     let (qualified_name, escaped_qualified_name) = (
-        qualified_name.display_verbatim(ctx.db()).to_string(),
+        qualified_name.unescaped().display(ctx.db()).to_string(),
         qualified_name.display(ctx.db(), completion.edition).to_string(),
     );
     let snippet_cap = ctx.snippet_cap();
diff --git a/crates/ide-completion/src/render/macro_.rs b/crates/ide-completion/src/render/macro_.rs
index e265e92f97..6490171fbb 100644
--- a/crates/ide-completion/src/render/macro_.rs
+++ b/crates/ide-completion/src/render/macro_.rs
@@ -46,19 +46,21 @@ fn render(
         ctx.source_range()
     };
 
-    let (name, escaped_name) =
-        (name.as_str(), name.display(ctx.db(), completion.edition).to_smolstr());
+    let (name, escaped_name) = (
+        name.unescaped().display(ctx.db()).to_smolstr(),
+        name.display(ctx.db(), completion.edition).to_smolstr(),
+    );
     let docs = ctx.docs(macro_);
     let docs_str = docs.as_ref().map(Documentation::as_str).unwrap_or_default();
     let is_fn_like = macro_.is_fn_like(completion.db);
-    let (bra, ket) = if is_fn_like { guess_macro_braces(name, docs_str) } else { ("", "") };
+    let (bra, ket) = if is_fn_like { guess_macro_braces(&name, docs_str) } else { ("", "") };
 
     let needs_bang = is_fn_like && !is_use_path && !has_macro_bang;
 
     let mut item = CompletionItem::new(
         SymbolKind::from(macro_.kind(completion.db)),
         source_range,
-        label(&ctx, needs_bang, bra, ket, &name.to_smolstr()),
+        label(&ctx, needs_bang, bra, ket, &name),
         completion.edition,
     );
     item.set_deprecated(ctx.is_deprecated(macro_))
@@ -69,11 +71,11 @@ fn render(
     match ctx.snippet_cap() {
         Some(cap) if needs_bang && !has_call_parens => {
             let snippet = format!("{escaped_name}!{bra}$0{ket}");
-            let lookup = banged_name(name);
+            let lookup = banged_name(&name);
             item.insert_snippet(cap, snippet).lookup_by(lookup);
         }
         _ if needs_bang => {
-            item.insert_text(banged_name(&escaped_name)).lookup_by(banged_name(name));
+            item.insert_text(banged_name(&escaped_name)).lookup_by(banged_name(&name));
         }
         _ => {
             cov_mark::hit!(dont_insert_macro_call_parens_unnecessary);
diff --git a/crates/ide-completion/src/render/pattern.rs b/crates/ide-completion/src/render/pattern.rs
index 124abb17b6..5675dfb5c6 100644
--- a/crates/ide-completion/src/render/pattern.rs
+++ b/crates/ide-completion/src/render/pattern.rs
@@ -31,11 +31,13 @@ pub(crate) fn render_struct_pat(
     }
 
     let name = local_name.unwrap_or_else(|| strukt.name(ctx.db()));
-    let (name, escaped_name) =
-        (name.as_str(), name.display(ctx.db(), ctx.completion.edition).to_smolstr());
+    let (name, escaped_name) = (
+        name.unescaped().display(ctx.db()).to_smolstr(),
+        name.display(ctx.db(), ctx.completion.edition).to_smolstr(),
+    );
     let kind = strukt.kind(ctx.db());
-    let label = format_literal_label(name, kind, ctx.snippet_cap());
-    let lookup = format_literal_lookup(name, kind);
+    let label = format_literal_label(name.as_str(), kind, ctx.snippet_cap());
+    let lookup = format_literal_lookup(name.as_str(), kind);
     let pat = render_pat(&ctx, pattern_ctx, &escaped_name, kind, &visible_fields, fields_omitted)?;
 
     let db = ctx.db();
@@ -59,13 +61,13 @@ pub(crate) fn render_variant_pat(
 
     let (name, escaped_name) = match path {
         Some(path) => (
-            path.display_verbatim(ctx.db()).to_smolstr(),
-            path.display(ctx.db(), ctx.completion.edition).to_smolstr(),
+            path.unescaped().display(ctx.db()).to_string().into(),
+            path.display(ctx.db(), ctx.completion.edition).to_string().into(),
         ),
         None => {
             let name = local_name.unwrap_or_else(|| variant.name(ctx.db()));
             let it = (
-                name.as_str().to_smolstr(),
+                name.unescaped().display(ctx.db()).to_smolstr(),
                 name.display(ctx.db(), ctx.completion.edition).to_smolstr(),
             );
             it
diff --git a/crates/ide-completion/src/render/type_alias.rs b/crates/ide-completion/src/render/type_alias.rs
index 1b952f3136..09eb19201c 100644
--- a/crates/ide-completion/src/render/type_alias.rs
+++ b/crates/ide-completion/src/render/type_alias.rs
@@ -32,11 +32,14 @@ fn render(
     let name = type_alias.name(db);
     let (name, escaped_name) = if with_eq {
         (
-            SmolStr::from_iter([&name.as_str().to_smolstr(), " = "]),
+            SmolStr::from_iter([&name.unescaped().display(db).to_smolstr(), " = "]),
             SmolStr::from_iter([&name.display_no_db(ctx.completion.edition).to_smolstr(), " = "]),
         )
     } else {
-        (name.as_str().to_smolstr(), name.display_no_db(ctx.completion.edition).to_smolstr())
+        (
+            name.unescaped().display(db).to_smolstr(),
+            name.display_no_db(ctx.completion.edition).to_smolstr(),
+        )
     };
     let detail = type_alias.display(db, ctx.completion.edition).to_string();
 
diff --git a/crates/ide-completion/src/render/union_literal.rs b/crates/ide-completion/src/render/union_literal.rs
index 7420362652..e053e299d9 100644
--- a/crates/ide-completion/src/render/union_literal.rs
+++ b/crates/ide-completion/src/render/union_literal.rs
@@ -23,12 +23,12 @@ pub(crate) fn render_union_literal(
 
     let (qualified_name, escaped_qualified_name) = match path {
         Some(p) => (
-            p.display_verbatim(ctx.db()).to_smolstr(),
-            p.display(ctx.db(), ctx.completion.edition).to_smolstr(),
+            p.unescaped().display(ctx.db()).to_string(),
+            p.display(ctx.db(), ctx.completion.edition).to_string(),
         ),
         None => (
-            name.as_str().to_smolstr(),
-            name.display(ctx.db(), ctx.completion.edition).to_smolstr(),
+            name.unescaped().display(ctx.db()).to_string(),
+            name.display(ctx.db(), ctx.completion.edition).to_string(),
         ),
     };
     let label = format_literal_label(
diff --git a/crates/ide-db/src/defs.rs b/crates/ide-db/src/defs.rs
index d12bda0816..49d26dfe25 100644
--- a/crates/ide-db/src/defs.rs
+++ b/crates/ide-db/src/defs.rs
@@ -794,7 +794,7 @@ impl NameRefClass {
                                 hir::AssocItem::TypeAlias(it) => Some(it),
                                 _ => None,
                             })
-                            .find(|alias| alias.name(sema.db).as_str() == name_ref.text().trim_start_matches("r#"))
+                            .find(|alias| alias.name(sema.db).eq_ident(name_ref.text().as_str()))
                         {
                             // No substitution, this can only occur in type position.
                             return Some(NameRefClass::Definition(Definition::TypeAlias(ty), None));
diff --git a/crates/ide-db/src/famous_defs.rs b/crates/ide-db/src/famous_defs.rs
index 2f4d07446f..1dc61e3f0a 100644
--- a/crates/ide-db/src/famous_defs.rs
+++ b/crates/ide-db/src/famous_defs.rs
@@ -142,13 +142,6 @@ impl FamousDefs<'_, '_> {
         self.find_macro("core:unimplemented")
     }
 
-    pub fn core_fmt_Display(&self) -> Option<Trait> {
-        self.find_trait("core:fmt:Display")
-    }
-
-    pub fn alloc_string_ToString(&self) -> Option<Trait> {
-        self.find_trait("alloc:string:ToString")
-    }
     pub fn builtin_crates(&self) -> impl Iterator<Item = Crate> {
         IntoIterator::into_iter([
             self.std(),
@@ -221,15 +214,14 @@ impl FamousDefs<'_, '_> {
         for segment in path {
             module = module.children(db).find_map(|child| {
                 let name = child.name(db)?;
-                if name.as_str() == segment {
+                if name.eq_ident(segment) {
                     Some(child)
                 } else {
                     None
                 }
             })?;
         }
-        let def =
-            module.scope(db, None).into_iter().find(|(name, _def)| name.as_str() == trait_)?.1;
+        let def = module.scope(db, None).into_iter().find(|(name, _def)| name.eq_ident(trait_))?.1;
         Some(def)
     }
 }
diff --git a/crates/ide-db/src/rename.rs b/crates/ide-db/src/rename.rs
index 59914bedde..42efbd68e3 100644
--- a/crates/ide-db/src/rename.rs
+++ b/crates/ide-db/src/rename.rs
@@ -263,12 +263,13 @@ fn rename_mod(
         //  - Module has submodules defined in separate files
         let dir_paths = match (is_mod_rs, has_detached_child, module.name(sema.db)) {
             // Go up one level since the anchor is inside the dir we're trying to rename
-            (true, _, Some(mod_name)) => {
-                Some((format!("../{}", mod_name.as_str()), format!("../{new_name}")))
-            }
+            (true, _, Some(mod_name)) => Some((
+                format!("../{}", mod_name.unescaped().display(sema.db)),
+                format!("../{new_name}"),
+            )),
             // The anchor is on the same level as target dir
             (false, true, Some(mod_name)) => {
-                Some((mod_name.as_str().to_owned(), new_name.to_owned()))
+                Some((mod_name.unescaped().display(sema.db).to_string(), new_name.to_owned()))
             }
             _ => None,
         };
diff --git a/crates/ide-db/src/search.rs b/crates/ide-db/src/search.rs
index 7fc563a424..a75aba137b 100644
--- a/crates/ide-db/src/search.rs
+++ b/crates/ide-db/src/search.rs
@@ -625,7 +625,7 @@ impl<'a> FindUsages<'a> {
             let _p = tracing::info_span!("collect_possible_aliases").entered();
 
             let db = sema.db;
-            let container_name = container.name(db).as_str().to_smolstr();
+            let container_name = container.name(db).unescaped().display(db).to_smolstr();
             let search_scope = Definition::from(container).search_scope(db);
             let mut seen = FxHashSet::default();
             let mut completed = FxHashSet::default();
@@ -925,8 +925,12 @@ impl<'a> FindUsages<'a> {
                             .or_else(|| ty.as_builtin().map(|builtin| builtin.name()))
                     })
                 };
-                // We need to search without the `r#`, hence `as_str` access.
-                self.def.name(sema.db).or_else(self_kw_refs).map(|it| it.as_str().to_smolstr())
+                // We need to unescape the name in case it is written without "r#" in earlier
+                // editions of Rust where it isn't a keyword.
+                self.def
+                    .name(sema.db)
+                    .or_else(self_kw_refs)
+                    .map(|it| it.unescaped().display(sema.db).to_smolstr())
             }
         };
         let name = match &name {
diff --git a/crates/ide-db/src/symbol_index.rs b/crates/ide-db/src/symbol_index.rs
index c94644eeb8..e5ce10a771 100644
--- a/crates/ide-db/src/symbol_index.rs
+++ b/crates/ide-db/src/symbol_index.rs
@@ -143,7 +143,7 @@ fn library_symbols(db: &dyn SymbolsDatabase, source_root_id: SourceRootId) -> Ar
 fn module_symbols(db: &dyn SymbolsDatabase, module: Module) -> Arc<SymbolIndex> {
     let _p = tracing::info_span!("module_symbols").entered();
 
-    Arc::new(SymbolIndex::new(SymbolCollector::collect_module(db.upcast(), module)))
+    Arc::new(SymbolIndex::new(SymbolCollector::new_module(db.upcast(), module)))
 }
 
 pub fn crate_symbols(db: &dyn SymbolsDatabase, krate: Crate) -> Box<[Arc<SymbolIndex>]> {
@@ -284,13 +284,15 @@ impl SymbolIndex {
             builder.insert(key, value).unwrap();
         }
 
-        // FIXME: fst::Map should ideally have a way to shrink the backing buffer without the unwrap dance
-        let map = fst::Map::new({
-            let mut buf = builder.into_inner().unwrap();
-            buf.shrink_to_fit();
-            buf
-        })
-        .unwrap();
+        let map = builder
+            .into_inner()
+            .and_then(|mut buf| {
+                fst::Map::new({
+                    buf.shrink_to_fit();
+                    buf
+                })
+            })
+            .unwrap();
         SymbolIndex { symbols, map }
     }
 
@@ -491,7 +493,7 @@ pub(self) use crate::Trait as IsThisJustATrait;
             .modules(&db)
             .into_iter()
             .map(|module_id| {
-                let mut symbols = SymbolCollector::collect_module(&db, module_id);
+                let mut symbols = SymbolCollector::new_module(&db, module_id);
                 symbols.sort_by_key(|it| it.name.as_str().to_owned());
                 (module_id, symbols)
             })
@@ -518,7 +520,7 @@ struct Duplicate;
             .modules(&db)
             .into_iter()
             .map(|module_id| {
-                let mut symbols = SymbolCollector::collect_module(&db, module_id);
+                let mut symbols = SymbolCollector::new_module(&db, module_id);
                 symbols.sort_by_key(|it| it.name.as_str().to_owned());
                 (module_id, symbols)
             })
diff --git a/crates/ide-db/src/ty_filter.rs b/crates/ide-db/src/ty_filter.rs
index 2fdd835863..515bc418cb 100644
--- a/crates/ide-db/src/ty_filter.rs
+++ b/crates/ide-db/src/ty_filter.rs
@@ -26,7 +26,7 @@ impl TryEnum {
             _ => return None,
         };
         TryEnum::ALL.iter().find_map(|&var| {
-            if enum_.name(sema.db).as_str() == var.type_name() {
+            if enum_.name(sema.db).eq_ident(var.type_name()) {
                 return Some(var);
             }
             None
diff --git a/crates/ide-diagnostics/src/handlers/unlinked_file.rs b/crates/ide-diagnostics/src/handlers/unlinked_file.rs
index f3109b9bb7..13591dfb2e 100644
--- a/crates/ide-diagnostics/src/handlers/unlinked_file.rs
+++ b/crates/ide-diagnostics/src/handlers/unlinked_file.rs
@@ -112,7 +112,7 @@ fn fixes(
                 // shouldn't occur
                 _ => continue 'crates,
             };
-            match current.children.iter().find(|(name, _)| name.as_str() == seg) {
+            match current.children.iter().find(|(name, _)| name.eq_ident(seg)) {
                 Some((_, &child)) => current = &crate_def_map[child],
                 None => continue 'crates,
             }
@@ -161,7 +161,7 @@ fn fixes(
             // try finding a parent that has an inline tree from here on
             let mut current = module;
             for s in stack.iter().rev() {
-                match module.children.iter().find(|(name, _)| name.as_str() == s) {
+                match module.children.iter().find(|(name, _)| name.eq_ident(s)) {
                     Some((_, child)) => {
                         current = &crate_def_map[*child];
                     }
diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs
index cfd8919730..bc9843f3f3 100644
--- a/crates/ide/src/doc_links.rs
+++ b/crates/ide/src/doc_links.rs
@@ -413,7 +413,8 @@ fn rewrite_url_link(db: &RootDatabase, def: Definition, target: &str) -> Option<
 fn mod_path_of_def(db: &RootDatabase, def: Definition) -> Option<String> {
     def.canonical_module_path(db).map(|it| {
         let mut path = String::new();
-        it.flat_map(|it| it.name(db)).for_each(|name| format_to!(path, "{}/", name.as_str()));
+        it.flat_map(|it| it.name(db))
+            .for_each(|name| format_to!(path, "{}/", name.unescaped().display(db)));
         path
     })
 }
@@ -589,10 +590,10 @@ fn filename_and_frag_for_def(
     let res = match def {
         Definition::Adt(adt) => match adt {
             Adt::Struct(s) => {
-                format!("struct.{}.html", s.name(db).as_str())
+                format!("struct.{}.html", s.name(db).unescaped().display(db.upcast()))
             }
-            Adt::Enum(e) => format!("enum.{}.html", e.name(db).as_str()),
-            Adt::Union(u) => format!("union.{}.html", u.name(db).as_str()),
+            Adt::Enum(e) => format!("enum.{}.html", e.name(db).unescaped().display(db.upcast())),
+            Adt::Union(u) => format!("union.{}.html", u.name(db).unescaped().display(db.upcast())),
         },
         Definition::Crate(_) => String::from("index.html"),
         Definition::Module(m) => match m.name(db) {
@@ -602,48 +603,48 @@ fn filename_and_frag_for_def(
                     Some(kw) => {
                         format!("keyword.{}.html", kw)
                     }
-                    None => format!("{}/index.html", name.as_str()),
+                    None => format!("{}/index.html", name.unescaped().display(db.upcast())),
                 }
             }
             None => String::from("index.html"),
         },
         Definition::Trait(t) => {
-            format!("trait.{}.html", t.name(db).as_str())
+            format!("trait.{}.html", t.name(db).unescaped().display(db.upcast()))
         }
         Definition::TraitAlias(t) => {
-            format!("traitalias.{}.html", t.name(db).as_str())
+            format!("traitalias.{}.html", t.name(db).unescaped().display(db.upcast()))
         }
         Definition::TypeAlias(t) => {
-            format!("type.{}.html", t.name(db).as_str())
+            format!("type.{}.html", t.name(db).unescaped().display(db.upcast()))
         }
         Definition::BuiltinType(t) => {
-            format!("primitive.{}.html", t.name().as_str())
+            format!("primitive.{}.html", t.name().unescaped().display(db.upcast()))
         }
         Definition::Function(f) => {
-            format!("fn.{}.html", f.name(db).as_str())
+            format!("fn.{}.html", f.name(db).unescaped().display(db.upcast()))
         }
         Definition::Variant(ev) => {
             format!(
                 "enum.{}.html#variant.{}",
-                ev.parent_enum(db).name(db).as_str(),
-                ev.name(db).as_str()
+                ev.parent_enum(db).name(db).unescaped().display(db.upcast()),
+                ev.name(db).unescaped().display(db.upcast())
             )
         }
         Definition::Const(c) => {
-            format!("const.{}.html", c.name(db)?.as_str())
+            format!("const.{}.html", c.name(db)?.unescaped().display(db.upcast()))
         }
         Definition::Static(s) => {
-            format!("static.{}.html", s.name(db).as_str())
+            format!("static.{}.html", s.name(db).unescaped().display(db.upcast()))
         }
         Definition::Macro(mac) => match mac.kind(db) {
             hir::MacroKind::Declarative
             | hir::MacroKind::BuiltIn
             | hir::MacroKind::Attr
             | hir::MacroKind::ProcMacro => {
-                format!("macro.{}.html", mac.name(db).as_str())
+                format!("macro.{}.html", mac.name(db).unescaped().display(db.upcast()))
             }
             hir::MacroKind::Derive => {
-                format!("derive.{}.html", mac.name(db).as_str())
+                format!("derive.{}.html", mac.name(db).unescaped().display(db.upcast()))
             }
         },
         Definition::Field(field) => {
@@ -653,7 +654,11 @@ fn filename_and_frag_for_def(
                 hir::VariantDef::Variant(it) => Definition::Variant(it),
             };
             let (_, file, _) = filename_and_frag_for_def(db, def)?;
-            return Some((def, file, Some(format!("structfield.{}", field.name(db).as_str()))));
+            return Some((
+                def,
+                file,
+                Some(format!("structfield.{}", field.name(db).unescaped().display(db.upcast()))),
+            ));
         }
         Definition::SelfType(impl_) => {
             let adt = impl_.self_ty(db).as_adt()?.into();
@@ -662,7 +667,7 @@ fn filename_and_frag_for_def(
             return Some((adt, file, Some(String::from("impl"))));
         }
         Definition::ExternCrateDecl(it) => {
-            format!("{}/index.html", it.name(db).as_str())
+            format!("{}/index.html", it.name(db).unescaped().display(db.upcast()))
         }
         Definition::Local(_)
         | Definition::GenericParam(_)
@@ -694,16 +699,16 @@ fn get_assoc_item_fragment(db: &dyn HirDatabase, assoc_item: hir::AssocItem) ->
             // Rustdoc makes this decision based on whether a method 'has defaultness'.
             // Currently this is only the case for provided trait methods.
             if is_trait_method && !function.has_body(db) {
-                format!("tymethod.{}", function.name(db).as_str())
+                format!("tymethod.{}", function.name(db).unescaped().display(db.upcast()))
             } else {
-                format!("method.{}", function.name(db).as_str())
+                format!("method.{}", function.name(db).unescaped().display(db.upcast()))
             }
         }
         AssocItem::Const(constant) => {
-            format!("associatedconstant.{}", constant.name(db)?.as_str())
+            format!("associatedconstant.{}", constant.name(db)?.unescaped().display(db.upcast()))
         }
         AssocItem::TypeAlias(ty) => {
-            format!("associatedtype.{}", ty.name(db).as_str())
+            format!("associatedtype.{}", ty.name(db).unescaped().display(db.upcast()))
         }
     })
 }
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs
index d18732a6b8..99d0d6af71 100644
--- a/crates/ide/src/goto_definition.rs
+++ b/crates/ide/src/goto_definition.rs
@@ -185,15 +185,6 @@ fn find_definition_for_known_blanket_dual_impls(
             // Extract the `T` from `Result<T, ..>`
             [return_type.type_arguments().next()?, callable.receiver_param(sema.db)?.1],
         )?
-    } else if fn_name == sym::to_string && fd.alloc_string_ToString() == Some(t) {
-        let dual = fd.core_fmt_Display()?;
-        let dual_f = dual.function(sema.db, &sym::fmt)?;
-        sema.resolve_trait_impl_method(
-            return_type.clone(),
-            dual,
-            dual_f,
-            [callable.receiver_param(sema.db)?.1.strip_reference()],
-        )?
     } else {
         return None;
     };
@@ -3240,36 +3231,6 @@ impl FromStr for A {
 }
 fn f() {
     let a: Result<A, _> = "aaaaaa".parse$0();
-}
-        "#,
-        );
-    }
-
-    #[test]
-    fn to_string_call_to_display_definition() {
-        check(
-            r#"
-//- minicore:fmt
-//- /alloc.rs crate:alloc
-pub mod string {
-    pub struct String;
-    pub trait ToString {
-        fn to_string(&self) -> String;
-    }
-
-    impl<T: core::fmt::Display> ToString for T {
-        fn to_string(&self) -> String { String }
-    }
-}
-//- /lib.rs crate:lib deps:alloc
-use alloc::string::ToString;
-struct A;
-impl core::fmt::Display for A {
-    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {}
-    // ^^^
-}
-fn f() {
-    A.to_string$0();
 }
         "#,
         );
diff --git a/crates/ide/src/inlay_hints/param_name.rs b/crates/ide/src/inlay_hints/param_name.rs
index a6f7e0c184..a7b066700c 100644
--- a/crates/ide/src/inlay_hints/param_name.rs
+++ b/crates/ide/src/inlay_hints/param_name.rs
@@ -124,7 +124,9 @@ fn should_hide_param_name_hint(
     }
 
     let fn_name = match callable.kind() {
-        hir::CallableKind::Function(it) => Some(it.name(sema.db).as_str().to_smolstr()),
+        hir::CallableKind::Function(it) => {
+            Some(it.name(sema.db).unescaped().display_no_db().to_smolstr())
+        }
         _ => None,
     };
     let fn_name = fn_name.as_deref();
diff --git a/crates/ide/src/rename.rs b/crates/ide/src/rename.rs
index 07dfd83c4e..ba739df309 100644
--- a/crates/ide/src/rename.rs
+++ b/crates/ide/src/rename.rs
@@ -263,7 +263,7 @@ fn find_definitions(
                         .and_then(|def| {
                             // if the name differs from the definitions name it has to be an alias
                             if def
-                                .name(sema.db).is_some_and(|it| it.as_str() != name_ref.text().trim_start_matches("r#"))
+                                .name(sema.db).is_some_and(|it| !it.eq_ident(name_ref.text().as_str()))
                             {
                                 Err(format_err!("Renaming aliases is currently unsupported"))
                             } else {
diff --git a/crates/intern/src/symbol/symbols.rs b/crates/intern/src/symbol/symbols.rs
index 7a090a6b6b..59c0c9dca1 100644
--- a/crates/intern/src/symbol/symbols.rs
+++ b/crates/intern/src/symbol/symbols.rs
@@ -459,9 +459,7 @@ define_symbols! {
     termination,
     test_case,
     test,
-    then,
     thiscall,
-    to_string,
     trace_macros,
     transmute_opts,
     transmute_trait,
diff --git a/crates/project-model/src/project_json.rs b/crates/project-model/src/project_json.rs
index a396396761..6a88cf022d 100644
--- a/crates/project-model/src/project_json.rs
+++ b/crates/project-model/src/project_json.rs
@@ -63,7 +63,7 @@ use crate::{ManifestPath, TargetKind};
 pub struct ProjectJson {
     /// e.g. `path/to/sysroot`
     pub(crate) sysroot: Option<AbsPathBuf>,
-    /// e.g. `path/to/sysroot/lib/rustlib/src/rust/library`
+    /// e.g. `path/to/sysroot/lib/rustlib/src/rust`
     pub(crate) sysroot_src: Option<AbsPathBuf>,
     project_root: AbsPathBuf,
     /// The path to the rust-project.json file. May be None if this
diff --git a/docs/user/manual.adoc b/docs/user/manual.adoc
index 4a2a6f2e36..ffc820e9b7 100644
--- a/docs/user/manual.adoc
+++ b/docs/user/manual.adoc
@@ -716,32 +716,6 @@ interface JsonProject {
     /// dependencies as well as sysroot crate (libstd,
     /// libcore and such).
     crates: Crate[];
-    /// Configuration for CLI commands.
-    ///
-    /// These are used for running and debugging binaries
-    /// and tests without encoding build system-specific
-    /// knowledge into rust-analyzer.
-    ///
-    /// # Example
-    ///
-    /// Below is an example of a test runnable. `{label}` and `{test_id}`
-    /// are explained in `Runnable::args`'s documentation below.
-    ///
-    /// ```json
-    /// {
-    ///     "program": "buck",
-    ///     "args": [
-    ///         "test",
-    ///          "{label}",
-    ///          "--",
-    ///          "{test_id}",
-    ///          "--print-passing-details"
-    ///     ],
-    ///     "cwd": "/home/user/repo-root/",
-    ///     "kind": "testOne"
-    /// }
-    /// ```
-    runnables?: Runnable[];
 }
 
 interface Crate {
@@ -752,10 +726,7 @@ interface Crate {
     /// Path to the root module of the crate.
     root_module: string;
     /// Edition of the crate.
-    edition: '2015' | '2018' | '2021' | '2024';
-    /// The version of the crate. Used for calculating
-    /// the correct docs.rs URL.
-    version?: string;
+    edition: "2015" | "2018" | "2021";
     /// Dependencies
     deps: Dep[];
     /// Should this crate be treated as a member of
@@ -786,9 +757,9 @@ interface Crate {
     /// rust-analyzer assumes that files from one
     /// source can't refer to files in another source.
     source?: {
-        include_dirs: string[];
-        exclude_dirs: string[];
-    };
+        include_dirs: string[],
+        exclude_dirs: string[],
+    },
     /// List of cfg groups this crate inherits.
     ///
     /// All cfg in these groups will be concatenated to
@@ -805,68 +776,21 @@ interface Crate {
     target?: string;
     /// Environment variables, used for
     /// the `env!` macro
-    env: { [key: string]: string; };
+    env: { [key: string]: string; },
 
     /// Whether the crate is a proc-macro crate.
     is_proc_macro: boolean;
     /// For proc-macro crates, path to compiled
     /// proc-macro (.so file).
     proc_macro_dylib_path?: string;
-
-    /// Repository, matching the URL that would be used
-    /// in Cargo.toml.
-    repository?: string;
-
-    /// Build-specific data about this crate.
-    build?: BuildInfo;
 }
 
 interface Dep {
     /// Index of a crate in the `crates` array.
-    crate: number;
+    crate: number,
     /// Name as should appear in the (implicit)
     /// `extern crate name` declaration.
-    name: string;
-}
-
-interface BuildInfo {
-    /// The name associated with this crate.
-    ///
-    /// This is determined by the build system that produced
-    /// the `rust-project.json` in question. For instance, if buck were used,
-    /// the label might be something like `//ide/rust/rust-analyzer:rust-analyzer`.
-    ///
-    /// Do not attempt to parse the contents of this string; it is a build system-specific
-    /// identifier similar to `Crate::display_name`.
-    label: string;
-    /// Path corresponding to the build system-specific file defining the crate.
-    build_file: string;
-    /// The kind of target.
-    ///
-    /// This information is used to determine what sort
-    /// of runnable codelens to provide, if any.
-    target_kind: 'bin' | 'lib' | 'test';
-}
-
-interface Runnable {
-    /// The program invoked by the runnable.
-    ///
-    /// For example, this might be `cargo`, `buck`, or `bazel`.
-    program: string;
-    /// The arguments passed to `program`.
-    args: string[];
-    /// The current working directory of the runnable.
-    cwd: string;
-    /// Used to decide what code lens to offer.
-    ///
-    /// `testOne`: This runnable will be used when the user clicks the 'Run Test'
-    /// CodeLens above a test.
-    ///
-    /// The args for testOne can contain two template strings:
-    /// `{label}` and `{test_id}`. `{label}` will be replaced
-    /// with the `Build::label` and `{test_id}` will be replaced
-    /// with the test name.
-    kind: 'testOne' | string;
+    name: string,
 }
 ----
 
diff --git a/lib/lsp-server/src/msg.rs b/lib/lsp-server/src/msg.rs
index 2749557b91..074bc43388 100644
--- a/lib/lsp-server/src/msg.rs
+++ b/lib/lsp-server/src/msg.rs
@@ -80,9 +80,9 @@ pub struct Request {
 
 #[derive(Debug, Serialize, Deserialize, Clone)]
 pub struct Response {
-    // JSON-RPC allows this to be null if we can't find or parse the
-    // request id. We fail deserialization in that case, so we just
-    // make this field mandatory.
+    // JSON RPC allows this to be null if it was impossible
+    // to decode the request's id. Ignore this special case
+    // and just die horribly.
     pub id: RequestId,
     #[serde(skip_serializing_if = "Option::is_none")]
     pub result: Option<serde_json::Value>,


Test patch:
diff --git a/crates/hir-def/src/body/tests/block.rs b/crates/hir-def/src/body/tests/block.rs
index f483efa851..e136dd18a5 100644
--- a/crates/hir-def/src/body/tests/block.rs
+++ b/crates/hir-def/src/body/tests/block.rs
@@ -475,7 +475,7 @@ fn outer() {
 
             block scope::tests
             name: _
-            outer: v
+            outer: vg
 
             crate
             outer: v
diff --git a/crates/hir-def/src/nameres/tests.rs b/crates/hir-def/src/nameres/tests.rs
index 318aee04f7..73fc6787bf 100644
--- a/crates/hir-def/src/nameres/tests.rs
+++ b/crates/hir-def/src/nameres/tests.rs
@@ -103,8 +103,8 @@ mod a {
             c: t
 
             crate::a::b::c
-            A: v
-            b: t
+            A: vg
+            b: tg
         "#]],
     );
 }
@@ -256,8 +256,8 @@ pub enum Foo { Bar, Baz }
 "#,
         expect![[r#"
             crate
-            Bar: t v
-            Baz: t v
+            Bar: tg vg
+            Baz: tg vg
         "#]],
     );
 }
@@ -421,10 +421,10 @@ pub struct NotExported;
 "#,
         expect![[r#"
             crate
-            Exported: t v
-            PublicItem: t v
-            allowed_reexport: t
-            exported: t
+            Exported: tg vg
+            PublicItem: tg vg
+            allowed_reexport: tg
+            exported: tg
             not_allowed_reexport1: _
             not_allowed_reexport2: _
         "#]],
@@ -692,7 +692,7 @@ mod b {
             b: t
 
             crate::a
-            T: t v
+            T: t vg
 
             crate::b
             T: v
diff --git a/crates/hir-def/src/nameres/tests/globs.rs b/crates/hir-def/src/nameres/tests/globs.rs
index 8963a57679..ddb9d4a134 100644
--- a/crates/hir-def/src/nameres/tests/globs.rs
+++ b/crates/hir-def/src/nameres/tests/globs.rs
@@ -18,9 +18,9 @@ pub struct Baz;
 "#,
         expect![[r#"
             crate
-            Baz: t v
-            Foo: t v
-            bar: t
+            Baz: tg vg
+            Foo: tg vg
+            bar: tg
             foo: t
 
             crate::foo
@@ -53,20 +53,20 @@ pub use super::*;
 "#,
         expect![[r#"
             crate
-            Baz: t v
-            Foo: t v
-            bar: t
+            Baz: tg vg
+            Foo: tg vg
+            bar: tg
             foo: t
 
             crate::foo
-            Baz: t v
+            Baz: tg vg
             Foo: t v
             bar: t
 
             crate::foo::bar
             Baz: t v
-            Foo: t v
-            bar: t
+            Foo: tg vg
+            bar: tg
         "#]],
     );
 }
@@ -91,20 +91,20 @@ pub use super::*;
 ",
         expect![[r#"
             crate
-            Baz: t v
-            bar: t
+            Baz: tg vg
+            bar: tg
             foo: t
 
             crate::foo
-            Baz: t v
+            Baz: tg vg
             PrivateStructFoo: t v
             bar: t
 
             crate::foo::bar
             Baz: t v
             PrivateStructBar: t v
-            PrivateStructFoo: t v
-            bar: t
+            PrivateStructFoo: tg vg
+            bar: tg
         "#]],
     );
 }
@@ -130,9 +130,9 @@ pub(crate) struct PubCrateStruct;
 ",
         expect![[r#"
             crate
-            Foo: t
-            PubCrateStruct: t v
-            bar: t
+            Foo: tg
+            PubCrateStruct: tg vg
+            bar: tg
             foo: t
 
             crate::foo
@@ -160,7 +160,7 @@ pub struct Baz;
 "#,
         expect![[r#"
             crate
-            Baz: t v
+            Baz: tg vg
         "#]],
     );
 }
@@ -178,7 +178,7 @@ struct Foo;
 "#,
         expect![[r#"
             crate
-            Baz: t v
+            Baz: tg vg
         "#]],
     );
 }
@@ -193,8 +193,8 @@ use self::Foo::*;
 "#,
         expect![[r#"
             crate
-            Bar: t v
-            Baz: t v
+            Bar: tg vg
+            Baz: tg vg
             Foo: t
         "#]],
     );
@@ -210,8 +210,8 @@ use self::Foo::{*};
 "#,
         expect![[r#"
             crate
-            Bar: t v
-            Baz: t v
+            Bar: tg vg
+            Baz: tg vg
             Foo: t
         "#]],
     );
@@ -359,7 +359,7 @@ use event::Event;
             event: t
 
             crate::event
-            Event: t v
+            Event: t vg
             serenity: t
 
             crate::event::serenity
@@ -388,10 +388,10 @@ use reexport::*;
 "#,
         expect![[r#"
             crate
-            Trait: t
+            Trait: tg
             defs: t
-            function: v
-            makro: m
+            function: vg
+            makro: mg
             reexport: t
 
             crate::defs
@@ -400,10 +400,10 @@ use reexport::*;
             makro: m
 
             crate::reexport
-            Trait: t
-            function: v
+            Trait: tg
+            function: vg
             inner: t
-            makro: m
+            makro: mg
 
             crate::reexport::inner
             Trait: ti
@@ -442,12 +442,12 @@ mod glob_target {
             ShouldBePrivate: t v
 
             crate::outer
-            ShouldBePrivate: t v
+            ShouldBePrivate: tg vg
             inner_superglob: t
 
             crate::outer::inner_superglob
-            ShouldBePrivate: t v
-            inner_superglob: t
+            ShouldBePrivate: tg vg
+            inner_superglob: tg
         "#]],
     );
 }
@@ -473,20 +473,20 @@ use reexport_2::*;
 "#,
         expect![[r#"
             crate
-            Placeholder: t v
+            Placeholder: tg vg
             libs: t
-            reexport_1: t
+            reexport_1: tg
             reexport_2: t
 
             crate::libs
             Placeholder: t v
 
             crate::reexport_2
-            Placeholder: t v
+            Placeholder: tg vg
             reexport_1: t
 
             crate::reexport_2::reexport_1
-            Placeholder: t v
+            Placeholder: tg vg
         "#]],
     );
 }
diff --git a/crates/hir-def/src/nameres/tests/macros.rs b/crates/hir-def/src/nameres/tests/macros.rs
index a05c4dcf9b..610886d55f 100644
--- a/crates/hir-def/src/nameres/tests/macros.rs
+++ b/crates/hir-def/src/nameres/tests/macros.rs
@@ -97,9 +97,9 @@ macro_rules! structs {
             bar: t
 
             crate::bar
-            Bar: t
-            Foo: t
-            bar: t
+            Bar: tg
+            Foo: tg
+            bar: tg
         "#]],
     );
 }
@@ -130,9 +130,9 @@ macro_rules! structs {
             bar: t
 
             crate::bar
-            Bar: t
-            Foo: t
-            bar: t
+            Bar: tg
+            Foo: tg
+            bar: tg
         "#]],
     );
 }
@@ -169,9 +169,9 @@ macro_rules! inner {
             bar: t
 
             crate::bar
-            Bar: t
-            Foo: t
-            bar: t
+            Bar: tg
+            Foo: tg
+            bar: tg
         "#]],
     );
 }
@@ -794,7 +794,7 @@ pub trait Clone {}
 "#,
         expect![[r#"
             crate
-            Clone: t m
+            Clone: tg mg
         "#]],
     );
 }
@@ -1075,9 +1075,9 @@ macro_rules! mbe {
 "#,
         expect![[r#"
             crate
-            DummyTrait: m
-            attribute_macro: m
-            function_like_macro: m
+            DummyTrait: mg
+            attribute_macro: mg
+            function_like_macro: mg
         "#]],
     );
 }