Repository: rust-lang/rust-analyzer
Pull request #19026 (2025-01-25 10:12:55)

Only collect implicit visibile use symbols if they have renames
Otherwise this will pollute the index too much with unnecessary symbols


Patch:
diff --git a/crates/hir-def/src/import_map.rs b/crates/hir-def/src/import_map.rs
index 34635997bd..bb780277ef 100644
--- a/crates/hir-def/src/import_map.rs
+++ b/crates/hir-def/src/import_map.rs
@@ -167,8 +167,8 @@ impl ImportMap {
                     let attr_id = if let Some(import) = import {
                         match import {
                             ImportOrExternCrate::ExternCrate(id) => Some(id.into()),
-                            ImportOrExternCrate::Import(id) => Some(id.use_.into()),
-                            ImportOrExternCrate::Glob(id) => Some(id.use_.into()),
+                            ImportOrExternCrate::Import(id) => Some(id.import.into()),
+                            ImportOrExternCrate::Glob(id) => Some(id.into()),
                         }
                     } else {
                         match item {
diff --git a/crates/hir-def/src/item_scope.rs b/crates/hir-def/src/item_scope.rs
index 65a39c5656..0ece878b83 100644
--- a/crates/hir-def/src/item_scope.rs
+++ b/crates/hir-def/src/item_scope.rs
@@ -31,7 +31,7 @@ pub struct PerNsGlobImports {
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub enum ImportOrExternCrate {
-    Glob(GlobId),
+    Glob(UseId),
     Import(ImportId),
     ExternCrate(ExternCrateId),
 }
@@ -45,33 +45,21 @@ impl From<ImportOrGlob> for ImportOrExternCrate {
     }
 }
 
-impl ImportOrExternCrate {
-    pub fn import_or_glob(self) -> Option<ImportOrGlob> {
-        match self {
-            ImportOrExternCrate::Import(it) => Some(ImportOrGlob::Import(it)),
-            ImportOrExternCrate::Glob(it) => Some(ImportOrGlob::Glob(it)),
-            _ => None,
-        }
-    }
-
-    pub fn import(self) -> Option<ImportId> {
-        match self {
-            ImportOrExternCrate::Import(it) => Some(it),
-            _ => None,
-        }
-    }
-
-    pub fn glob(self) -> Option<GlobId> {
-        match self {
-            ImportOrExternCrate::Glob(id) => Some(id),
-            _ => None,
+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),
         }
     }
+}
 
-    pub fn use_(self) -> Option<UseId> {
+impl ImportOrExternCrate {
+    pub fn into_import(self) -> Option<ImportOrGlob> {
         match self {
-            ImportOrExternCrate::Glob(id) => Some(id.use_),
-            ImportOrExternCrate::Import(id) => Some(id.use_),
+            ImportOrExternCrate::Import(it) => Some(ImportOrGlob::Import(it)),
+            ImportOrExternCrate::Glob(it) => Some(ImportOrGlob::Glob(it)),
             _ => None,
         }
     }
@@ -79,7 +67,7 @@ impl ImportOrExternCrate {
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub enum ImportOrGlob {
-    Glob(GlobId),
+    Glob(UseId),
     Import(ImportId),
 }
 
@@ -91,11 +79,17 @@ impl ImportOrGlob {
         }
     }
 }
+#[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(GlobId),
+    Glob(UseId),
     ExternCrate(ExternCrateId),
     Def(ModuleDefId),
 }
@@ -121,13 +115,7 @@ impl From<ImportOrGlob> for ImportOrDef {
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
 pub struct ImportId {
-    pub use_: UseId,
-    pub idx: Idx<ast::UseTree>,
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
-pub struct GlobId {
-    pub use_: UseId,
+    pub import: UseId,
     pub idx: Idx<ast::UseTree>,
 }
 
@@ -248,7 +236,7 @@ impl ItemScope {
         self.use_imports_types
             .keys()
             .copied()
-            .filter_map(ImportOrExternCrate::import_or_glob)
+            .filter_map(ImportOrExternCrate::into_import)
             .chain(self.use_imports_values.keys().copied())
             .chain(self.use_imports_macros.keys().copied())
             .filter_map(ImportOrGlob::into_import)
@@ -264,7 +252,7 @@ impl ItemScope {
         while let Some(&m) = scope.use_imports_macros.get(&ImportOrGlob::Import(import)) {
             match m {
                 ImportOrDef::Import(i) => {
-                    let module_id = i.use_.lookup(db).container;
+                    let module_id = i.import.lookup(db).container;
                     def_map = module_id.def_map(db);
                     scope = &def_map[module_id.local_id].scope;
                     import = i;
@@ -280,7 +268,7 @@ impl ItemScope {
         while let Some(&m) = scope.use_imports_types.get(&ImportOrExternCrate::Import(import)) {
             match m {
                 ImportOrDef::Import(i) => {
-                    let module_id = i.use_.lookup(db).container;
+                    let module_id = i.import.lookup(db).container;
                     def_map = module_id.def_map(db);
                     scope = &def_map[module_id.local_id].scope;
                     import = i;
@@ -296,7 +284,7 @@ impl ItemScope {
         while let Some(&m) = scope.use_imports_values.get(&ImportOrGlob::Import(import)) {
             match m {
                 ImportOrDef::Import(i) => {
-                    let module_id = i.use_.lookup(db).container;
+                    let module_id = i.import.lookup(db).container;
                     def_map = module_id.def_map(db);
                     scope = &def_map[module_id.local_id].scope;
                     import = i;
@@ -557,13 +545,9 @@ impl ItemScope {
         self.unnamed_trait_imports.get(&tr).map(|trait_| trait_.vis)
     }
 
-    pub(crate) fn push_unnamed_trait(
-        &mut self,
-        tr: TraitId,
-        vis: Visibility,
-        import: Option<ImportId>,
-    ) {
-        self.unnamed_trait_imports.insert(tr, Item { def: (), vis, import });
+    pub(crate) fn push_unnamed_trait(&mut self, tr: TraitId, vis: Visibility) {
+        // FIXME: import
+        self.unnamed_trait_imports.insert(tr, Item { def: (), vis, import: None });
     }
 
     pub(crate) fn push_res_with_import(
@@ -571,7 +555,7 @@ impl ItemScope {
         glob_imports: &mut PerNsGlobImports,
         lookup: (LocalModuleId, Name),
         def: PerNs,
-        import: Option<ImportOrExternCrate>,
+        import: Option<ImportType>,
     ) -> bool {
         let mut changed = false;
 
@@ -582,11 +566,12 @@ impl ItemScope {
             match existing {
                 Entry::Vacant(entry) => {
                     match import {
-                        Some(ImportOrExternCrate::Glob(_)) => {
+                        Some(ImportType::Glob(_)) => {
                             glob_imports.types.insert(lookup.clone());
                         }
                         _ => _ = glob_imports.types.remove(&lookup),
                     }
+                    let import = import.map(Into::into);
                     let prev = std::mem::replace(&mut fld.import, import);
                     if let Some(import) = import {
                         self.use_imports_types
@@ -597,7 +582,7 @@ impl ItemScope {
                 }
                 Entry::Occupied(mut entry) => {
                     match import {
-                        Some(ImportOrExternCrate::Glob(..)) => {
+                        Some(ImportType::Glob(..)) => {
                             // Multiple globs may import the same item and they may
                             // override visibility from previously resolved globs. This is
                             // currently handled by `DefCollector`, because we need to
@@ -606,6 +591,7 @@ impl ItemScope {
                         }
                         _ => {
                             if glob_imports.types.remove(&lookup) {
+                                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(
@@ -628,12 +614,16 @@ impl ItemScope {
             match existing {
                 Entry::Vacant(entry) => {
                     match import {
-                        Some(ImportOrExternCrate::Glob(_)) => {
+                        Some(ImportType::Glob(_)) => {
                             glob_imports.values.insert(lookup.clone());
                         }
                         _ => _ = glob_imports.values.remove(&lookup),
                     }
-                    let import = import.and_then(ImportOrExternCrate::import_or_glob);
+                    let import = match 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
@@ -642,13 +632,15 @@ impl ItemScope {
                     entry.insert(fld);
                     changed = true;
                 }
-                Entry::Occupied(mut entry)
-                    if !matches!(import, Some(ImportOrExternCrate::Glob(..))) =>
-                {
+                Entry::Occupied(mut entry) if !matches!(import, Some(ImportType::Glob(..))) => {
                     if glob_imports.values.remove(&lookup) {
                         cov_mark::hit!(import_shadowed);
 
-                        let import = import.and_then(ImportOrExternCrate::import_or_glob);
+                        let import = match 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
@@ -667,12 +659,16 @@ impl ItemScope {
             match existing {
                 Entry::Vacant(entry) => {
                     match import {
-                        Some(ImportOrExternCrate::Glob(_)) => {
+                        Some(ImportType::Glob(_)) => {
                             glob_imports.macros.insert(lookup.clone());
                         }
                         _ => _ = glob_imports.macros.remove(&lookup),
                     }
-                    let import = import.and_then(ImportOrExternCrate::import_or_glob);
+                    let import = match 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(
@@ -683,12 +679,14 @@ impl ItemScope {
                     entry.insert(fld);
                     changed = true;
                 }
-                Entry::Occupied(mut entry)
-                    if !matches!(import, Some(ImportOrExternCrate::Glob(..))) =>
-                {
+                Entry::Occupied(mut entry) if !matches!(import, Some(ImportType::Glob(..))) => {
                     if glob_imports.macros.remove(&lookup) {
                         cov_mark::hit!(import_shadowed);
-                        let import = import.and_then(ImportOrExternCrate::import_or_glob);
+                        let import = match 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(
@@ -858,7 +856,7 @@ impl PerNs {
         match def {
             ModuleDefId::ModuleId(_) => PerNs::types(def, v, import),
             ModuleDefId::FunctionId(_) => {
-                PerNs::values(def, v, import.and_then(ImportOrExternCrate::import_or_glob))
+                PerNs::values(def, v, import.and_then(ImportOrExternCrate::into_import))
             }
             ModuleDefId::AdtId(adt) => match adt {
                 AdtId::UnionId(_) => PerNs::types(def, v, import),
@@ -873,14 +871,14 @@ impl PerNs {
             },
             ModuleDefId::EnumVariantId(_) => PerNs::both(def, def, v, import),
             ModuleDefId::ConstId(_) | ModuleDefId::StaticId(_) => {
-                PerNs::values(def, v, import.and_then(ImportOrExternCrate::import_or_glob))
+                PerNs::values(def, v, import.and_then(ImportOrExternCrate::into_import))
             }
             ModuleDefId::TraitId(_) => PerNs::types(def, v, import),
             ModuleDefId::TraitAliasId(_) => PerNs::types(def, v, import),
             ModuleDefId::TypeAliasId(_) => PerNs::types(def, v, import),
             ModuleDefId::BuiltinType(_) => PerNs::types(def, v, import),
             ModuleDefId::MacroId(mac) => {
-                PerNs::macros(mac, v, import.and_then(ImportOrExternCrate::import_or_glob))
+                PerNs::macros(mac, v, import.and_then(ImportOrExternCrate::into_import))
             }
         }
     }
diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs
index 06276335b7..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::{GlobId, ImportId, ImportOrExternCrate, 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,
@@ -208,7 +208,7 @@ struct DefCollector<'a> {
     def_map: DefMap,
     // The dependencies of the current crate, including optional deps like `test`.
     deps: FxHashMap<Name, Dependency>,
-    glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, Visibility, GlobId)>>,
+    glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, Visibility, UseId)>>,
     unresolved_imports: Vec<ImportDirective>,
     indeterminate_imports: Vec<(ImportDirective, PerNs)>,
     unresolved_macros: Vec<MacroDirective>,
@@ -524,7 +524,14 @@ impl DefCollector<'_> {
 
         match per_ns.types {
             Some(Item { def: ModuleDefId::ModuleId(m), import, .. }) => {
-                self.def_map.prelude = Some((m, import.and_then(ImportOrExternCrate::use_)));
+                // 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)
+                        .and_then(ImportOrGlob::into_import)
+                        .map(|it| it.import),
+                ));
             }
             types => {
                 tracing::debug!(
@@ -841,14 +848,13 @@ impl DefCollector<'_> {
                     def.values = None;
                     def.macros = None;
                 }
-                let imp = ImportOrExternCrate::Import(ImportId { use_: id, idx: use_tree });
+                let imp = ImportType::Import(ImportId { import: id, idx: use_tree });
                 tracing::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def);
 
                 self.update(module_id, &[(name.cloned(), def)], vis, Some(imp));
             }
-            ImportSource { kind: ImportKind::Glob, id, is_prelude, use_tree } => {
+            ImportSource { kind: ImportKind::Glob, id, is_prelude, .. } => {
                 tracing::debug!("glob import: {:?}", import);
-                let glob = GlobId { use_: id, idx: use_tree };
                 match def.take_types() {
                     Some(ModuleDefId::ModuleId(m)) => {
                         if is_prelude {
@@ -872,12 +878,7 @@ impl DefCollector<'_> {
                                 .filter(|(_, res)| !res.is_none())
                                 .collect::<Vec<_>>();
 
-                            self.update(
-                                module_id,
-                                &items,
-                                vis,
-                                Some(ImportOrExternCrate::Glob(glob)),
-                            );
+                            self.update(module_id, &items, vis, Some(ImportType::Glob(id)));
                         } else {
                             // glob import from same crate => we do an initial
                             // import, and then need to propagate any further
@@ -909,16 +910,11 @@ impl DefCollector<'_> {
                                 .filter(|(_, res)| !res.is_none())
                                 .collect::<Vec<_>>();
 
-                            self.update(
-                                module_id,
-                                &items,
-                                vis,
-                                Some(ImportOrExternCrate::Glob(glob)),
-                            );
+                            self.update(module_id, &items, vis, Some(ImportType::Glob(id)));
                             // record the glob import in case we add further items
-                            let glob_imports = self.glob_imports.entry(m.local_id).or_default();
-                            match glob_imports.iter_mut().find(|(mid, _, _)| *mid == module_id) {
-                                None => glob_imports.push((module_id, vis, glob)),
+                            let glob = self.glob_imports.entry(m.local_id).or_default();
+                            match glob.iter_mut().find(|(mid, _, _)| *mid == module_id) {
+                                None => glob.push((module_id, vis, id)),
                                 Some((_, old_vis, _)) => {
                                     if let Some(new_vis) = old_vis.max(vis, &self.def_map) {
                                         *old_vis = new_vis;
@@ -951,12 +947,7 @@ impl DefCollector<'_> {
                             (Some(name), res)
                         })
                         .collect::<Vec<_>>();
-                        self.update(
-                            module_id,
-                            &resolutions,
-                            vis,
-                            Some(ImportOrExternCrate::Glob(glob)),
-                        );
+                        self.update(module_id, &resolutions, vis, Some(ImportType::Glob(id)));
                     }
                     Some(d) => {
                         tracing::debug!("glob import {:?} from non-module/enum {:?}", import, d);
@@ -976,7 +967,7 @@ impl DefCollector<'_> {
         resolutions: &[(Option<Name>, PerNs)],
         // Visibility this import will have
         vis: Visibility,
-        import: Option<ImportOrExternCrate>,
+        import: Option<ImportType>,
     ) {
         self.db.unwind_if_cancelled();
         self.update_recursive(module_id, resolutions, vis, import, 0)
@@ -990,7 +981,7 @@ impl DefCollector<'_> {
         // All resolutions are imported with this visibility; the visibilities in
         // the `PerNs` values are ignored and overwritten
         vis: Visibility,
-        import: Option<ImportOrExternCrate>,
+        import: Option<ImportType>,
         depth: usize,
     ) {
         if GLOB_RECURSION_LIMIT.check(depth).is_err() {
@@ -1006,10 +997,8 @@ impl DefCollector<'_> {
                         self.push_res_and_update_glob_vis(module_id, name, *res, vis, import);
                 }
                 None => {
-                    let (tr, import) = match res.take_types_full() {
-                        Some(Item { def: ModuleDefId::TraitId(tr), vis: _, import }) => {
-                            (tr, import)
-                        }
+                    let tr = match res.take_types() {
+                        Some(ModuleDefId::TraitId(tr)) => tr,
                         Some(other) => {
                             tracing::debug!("non-trait `_` import of {:?}", other);
                             continue;
@@ -1035,11 +1024,7 @@ impl DefCollector<'_> {
 
                     if should_update {
                         changed = true;
-                        self.def_map.modules[module_id].scope.push_unnamed_trait(
-                            tr,
-                            vis,
-                            import.and_then(ImportOrExternCrate::import),
-                        );
+                        self.def_map.modules[module_id].scope.push_unnamed_trait(tr, vis);
                     }
                 }
             }
@@ -1061,13 +1046,13 @@ impl DefCollector<'_> {
             .cloned()
             .collect::<Vec<_>>();
 
-        for (glob_importing_module, glob_import_vis, glob) in glob_imports {
+        for (glob_importing_module, glob_import_vis, use_) in glob_imports {
             let vis = glob_import_vis.min(vis, &self.def_map).unwrap_or(glob_import_vis);
             self.update_recursive(
                 glob_importing_module,
                 resolutions,
                 vis,
-                Some(ImportOrExternCrate::Glob(glob)),
+                Some(ImportType::Glob(use_)),
                 depth + 1,
             );
         }
@@ -1079,7 +1064,7 @@ impl DefCollector<'_> {
         name: &Name,
         mut defs: PerNs,
         vis: Visibility,
-        def_import_type: Option<ImportOrExternCrate>,
+        def_import_type: Option<ImportType>,
     ) -> bool {
         // `extern crate crate_name` things can be re-exported as `pub use crate_name`.
         // But they cannot be re-exported as `pub use self::crate_name`, `pub use crate::crate_name`
@@ -1092,10 +1077,10 @@ impl DefCollector<'_> {
                 let Some(ImportOrExternCrate::ExternCrate(_)) = def.import else {
                     return false;
                 };
-                let Some(ImportOrExternCrate::Import(id)) = def_import_type else {
+                let Some(ImportType::Import(id)) = def_import_type else {
                     return false;
                 };
-                let use_id = id.use_.lookup(self.db).id;
+                let use_id = id.import.lookup(self.db).id;
                 let item_tree = use_id.item_tree(self.db);
                 let use_kind = item_tree[use_id.value].use_tree.kind();
                 let UseTreeKind::Single { path, .. } = use_kind else {
@@ -1118,7 +1103,7 @@ impl DefCollector<'_> {
 
         let mut changed = false;
 
-        if let Some(ImportOrExternCrate::Glob(_)) = def_import_type {
+        if let Some(ImportType::Glob(_)) = def_import_type {
             let prev_defs = self.def_map[module_id].scope.get(name);
 
             // Multiple globs may import the same item and they may override visibility from
@@ -1745,7 +1730,7 @@ impl ModCollector<'_, '_> {
                                 ),
                             )],
                             vis,
-                            Some(ImportOrExternCrate::ExternCrate(id)),
+                            Some(ImportType::ExternCrate(id)),
                         );
                     } else {
                         if let Some(name) = name {
diff --git a/crates/hir-def/src/per_ns.rs b/crates/hir-def/src/per_ns.rs
index c2d3f67f17..339786fc01 100644
--- a/crates/hir-def/src/per_ns.rs
+++ b/crates/hir-def/src/per_ns.rs
@@ -78,7 +78,7 @@ impl PerNs {
             values: Some(Item {
                 def: values,
                 vis,
-                import: import.and_then(ImportOrExternCrate::import_or_glob),
+                import: import.and_then(ImportOrExternCrate::into_import),
             }),
             macros: None,
         }
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 0cbc75726b..4938478bb1 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -45,7 +45,7 @@ use hir_def::{
     body::BodyDiagnostic,
     data::{adt::VariantData, TraitFlags},
     generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance},
-    hir::{BindingAnnotation, BindingId, Expr, ExprId, ExprOrPatId, LabelId, Pat},
+    hir::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, LabelId, Pat},
     item_tree::{AttrOwner, FieldParent, ItemTreeFieldId, ItemTreeNode},
     lang_item::LangItemTarget,
     layout::{self, ReprOptions, TargetDataLayout},
@@ -2470,31 +2470,20 @@ impl Param {
     }
 
     pub fn as_local(&self, db: &dyn HirDatabase) -> Option<Local> {
-        match self.func {
-            Callee::Def(CallableDefId::FunctionId(it)) => {
-                let parent = DefWithBodyId::FunctionId(it);
-                let body = db.body(parent);
-                if let Some(self_param) = body.self_param.filter(|_| self.idx == 0) {
-                    Some(Local { parent, binding_id: self_param })
-                } else if let Pat::Bind { id, .. } =
-                    &body[body.params[self.idx - body.self_param.is_some() as usize]]
-                {
-                    Some(Local { parent, binding_id: *id })
-                } else {
-                    None
-                }
-            }
-            Callee::Closure(closure, _) => {
-                let c = db.lookup_intern_closure(closure.into());
-                let body = db.body(c.0);
-                if let Expr::Closure { args, .. } = &body[c.1] {
-                    if let Pat::Bind { id, .. } = &body[args[self.idx]] {
-                        return Some(Local { parent: c.0, binding_id: *id });
-                    }
-                }
-                None
-            }
-            _ => None,
+        let parent = match self.func {
+            Callee::Def(CallableDefId::FunctionId(it)) => DefWithBodyId::FunctionId(it),
+            Callee::Closure(closure, _) => db.lookup_intern_closure(closure.into()).0,
+            _ => return None,
+        };
+        let body = db.body(parent);
+        if let Some(self_param) = body.self_param.filter(|_| self.idx == 0) {
+            Some(Local { parent, binding_id: self_param })
+        } else if let Pat::Bind { id, .. } =
+            &body[body.params[self.idx - body.self_param.is_some() as usize]]
+        {
+            Some(Local { parent, binding_id: *id })
+        } else {
+            None
         }
     }
 
diff --git a/crates/hir/src/symbols.rs b/crates/hir/src/symbols.rs
index c1c45d8175..db6ed8b3e7 100644
--- a/crates/hir/src/symbols.rs
+++ b/crates/hir/src/symbols.rs
@@ -158,24 +158,32 @@ impl<'a> SymbolCollector<'a> {
         // Nested trees are very common, so a cache here will hit a lot.
         let import_child_source_cache = &mut FxHashMap::default();
 
-        let mut push_import = |this: &mut Self, i: ImportId, name: &Name, def: ModuleDefId| {
+        let is_explicit_import = |vis| match vis {
+            Visibility::Public => true,
+            Visibility::Module(_, VisibilityExplicitness::Explicit) => true,
+            Visibility::Module(_, VisibilityExplicitness::Implicit) => false,
+        };
+
+        let mut push_import = |this: &mut Self, i: ImportId, name: &Name, def: ModuleDefId, vis| {
             let source = import_child_source_cache
-                .entry(i.use_)
-                .or_insert_with(|| i.use_.child_source(this.db.upcast()));
+                .entry(i.import)
+                .or_insert_with(|| i.import.child_source(this.db.upcast()));
             let Some(use_tree_src) = source.value.get(i.idx) else { return };
-            let Some(name_ptr) = use_tree_src
-                .rename()
-                .and_then(|rename| rename.name())
-                .map(Either::Left)
-                .or_else(|| use_tree_src.path()?.segment()?.name_ref().map(Either::Right))
-                .map(|it| AstPtr::new(&it))
-            else {
+            let rename = use_tree_src.rename().and_then(|rename| rename.name());
+            let name_syntax = match rename {
+                Some(name) => Some(Either::Left(name)),
+                None if is_explicit_import(vis) => {
+                    (|| use_tree_src.path()?.segment()?.name_ref().map(Either::Right))()
+                }
+                None => None,
+            };
+            let Some(name_syntax) = name_syntax else {
                 return;
             };
             let dec_loc = DeclarationLocation {
                 hir_file_id: source.file_id,
                 ptr: SyntaxNodePtr::new(use_tree_src.syntax()),
-                name_ptr,
+                name_ptr: AstPtr::new(&name_syntax),
             };
             this.symbols.insert(FileSymbol {
                 name: name.symbol().clone(),
@@ -188,23 +196,23 @@ impl<'a> SymbolCollector<'a> {
         };
 
         let push_extern_crate =
-            |this: &mut Self, i: ExternCrateId, name: &Name, def: ModuleDefId| {
+            |this: &mut Self, i: ExternCrateId, name: &Name, def: ModuleDefId, vis| {
                 let loc = i.lookup(this.db.upcast());
                 let source = loc.source(this.db.upcast());
-                let Some(name_ptr) = source
-                    .value
-                    .rename()
-                    .and_then(|rename| rename.name())
-                    .map(Either::Left)
-                    .or_else(|| source.value.name_ref().map(Either::Right))
-                    .map(|it| AstPtr::new(&it))
-                else {
+                let rename = source.value.rename().and_then(|rename| rename.name());
+
+                let name_syntax = match rename {
+                    Some(name) => Some(Either::Left(name)),
+                    None if is_explicit_import(vis) => None,
+                    None => source.value.name_ref().map(Either::Right),
+                };
+                let Some(name_syntax) = name_syntax else {
                     return;
                 };
                 let dec_loc = DeclarationLocation {
                     hir_file_id: source.file_id,
                     ptr: SyntaxNodePtr::new(source.value.syntax()),
-                    name_ptr,
+                    name_ptr: AstPtr::new(&name_syntax),
                 };
                 this.symbols.insert(FileSymbol {
                     name: name.symbol().clone(),
@@ -216,18 +224,6 @@ impl<'a> SymbolCollector<'a> {
                 });
             };
 
-        let is_explicit_import = |vis| {
-            match vis {
-                Visibility::Module(_, VisibilityExplicitness::Explicit) => true,
-                Visibility::Module(_, VisibilityExplicitness::Implicit) => {
-                    // consider imports in the crate root explicit, as these are visibly
-                    // crate-wide anyways
-                    module_id.is_crate_root()
-                }
-                Visibility::Public => true,
-            }
-        };
-
         let def_map = module_id.def_map(self.db.upcast());
         let scope = &def_map[module_id.local_id].scope;
 
@@ -237,15 +233,14 @@ impl<'a> SymbolCollector<'a> {
 
         for (name, Item { def, vis, import }) in scope.types() {
             if let Some(i) = import {
-                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)
-                        }
+                match i {
+                    ImportOrExternCrate::Import(i) => push_import(self, i, name, def, vis),
+                    ImportOrExternCrate::Glob(_) => (),
+                    ImportOrExternCrate::ExternCrate(i) => {
+                        push_extern_crate(self, i, name, def, vis)
                     }
                 }
+
                 continue;
             }
             // self is a declaration
@@ -254,11 +249,9 @@ impl<'a> SymbolCollector<'a> {
 
         for (name, Item { def, vis, import }) in scope.macros() {
             if let Some(i) = import {
-                if is_explicit_import(vis) {
-                    match i {
-                        ImportOrGlob::Import(i) => push_import(self, i, name, def.into()),
-                        ImportOrGlob::Glob(_) => (),
-                    }
+                match i {
+                    ImportOrGlob::Import(i) => push_import(self, i, name, def.into(), vis),
+                    ImportOrGlob::Glob(_) => (),
                 }
                 continue;
             }
@@ -268,11 +261,9 @@ impl<'a> SymbolCollector<'a> {
 
         for (name, Item { def, vis, import }) in scope.values() {
             if let Some(i) = import {
-                if is_explicit_import(vis) {
-                    match i {
-                        ImportOrGlob::Import(i) => push_import(self, i, name, def),
-                        ImportOrGlob::Glob(_) => (),
-                    }
+                match i {
+                    ImportOrGlob::Import(i) => push_import(self, i, name, def, vis),
+                    ImportOrGlob::Glob(_) => (),
                 }
                 continue;
             }
diff --git a/crates/ide-assists/src/handlers/extract_variable.rs b/crates/ide-assists/src/handlers/extract_variable.rs
index 7b6f76d004..97321f4ec1 100644
--- a/crates/ide-assists/src/handlers/extract_variable.rs
+++ b/crates/ide-assists/src/handlers/extract_variable.rs
@@ -1672,8 +1672,8 @@ macro_rules! vec {
     () => {Vec}
 }
 fn main() {
-    let $0items = vec![];
-    let _ = items;
+    let $0vec = vec![];
+    let _ = vec;
 }
 "#,
             "Extract into variable",
@@ -1696,8 +1696,8 @@ macro_rules! vec {
     () => {Vec}
 }
 fn main() {
-    const $0ITEMS: Vec = vec![];
-    let _ = ITEMS;
+    const $0VEC: Vec = vec![];
+    let _ = VEC;
 }
 "#,
             "Extract into constant",
@@ -1720,8 +1720,8 @@ macro_rules! vec {
     () => {Vec}
 }
 fn main() {
-    static $0ITEMS: Vec = vec![];
-    let _ = ITEMS;
+    static $0VEC: Vec = vec![];
+    let _ = VEC;
 }
 "#,
             "Extract into static",
@@ -2019,8 +2019,8 @@ impl<T> Vec<T> {
 }
 
 fn foo(s: &mut S) {
-    let $0items = &mut s.vec;
-    items.push(0);
+    let $0vec = &mut s.vec;
+    vec.push(0);
 }"#,
             "Extract into variable",
         );
@@ -2106,8 +2106,8 @@ impl<T> Vec<T> {
 }
 
 fn foo(f: &mut Y) {
-    let $0items = &mut f.field.field.vec;
-    items.push(0);
+    let $0vec = &mut f.field.field.vec;
+    vec.push(0);
 }"#,
             "Extract into variable",
         );
diff --git a/crates/ide-db/src/syntax_helpers/suggest_name.rs b/crates/ide-db/src/syntax_helpers/suggest_name.rs
index 0a7141c19b..557c95f704 100644
--- a/crates/ide-db/src/syntax_helpers/suggest_name.rs
+++ b/crates/ide-db/src/syntax_helpers/suggest_name.rs
@@ -31,12 +31,6 @@ const USELESS_NAME_PREFIXES: &[&str] = &["from_", "with_", "into_"];
 /// `Result<User, Error>` -> `User`
 const WRAPPER_TYPES: &[&str] = &["Box", "Arc", "Rc", "Option", "Result"];
 
-/// Generic types replaced by a plural of their first argument.
-///
-/// # Examples
-/// `Vec<Name>` -> "names"
-const SEQUENCE_TYPES: &[&str] = &["Vec", "VecDeque", "LinkedList"];
-
 /// Prefixes to strip from methods names
 ///
 /// # Examples
@@ -384,11 +378,6 @@ fn name_of_type(ty: &hir::Type, db: &RootDatabase, edition: Edition) -> Option<S
             return name_of_type(&inner_ty, db, edition);
         }
 
-        if SEQUENCE_TYPES.contains(&name.as_str()) {
-            let inner_ty = ty.type_arguments().next();
-            return Some(sequence_name(inner_ty.as_ref(), db, edition));
-        }
-
         name
     } else if let Some(trait_) = ty.as_dyn_trait() {
         trait_name(&trait_, db, edition)?
@@ -401,32 +390,12 @@ fn name_of_type(ty: &hir::Type, db: &RootDatabase, edition: Edition) -> Option<S
         name
     } else if let Some(inner_ty) = ty.remove_ref() {
         return name_of_type(&inner_ty, db, edition);
-    } else if let Some(inner_ty) = ty.as_slice() {
-        return Some(sequence_name(Some(&inner_ty), db, edition));
     } else {
         return None;
     };
     normalize(&name)
 }
 
-fn sequence_name(inner_ty: Option<&hir::Type>, db: &RootDatabase, edition: Edition) -> SmolStr {
-    let items_str = SmolStr::new_static("items");
-    let Some(inner_ty) = inner_ty else {
-        return items_str;
-    };
-    let Some(name) = name_of_type(inner_ty, db, edition) else {
-        return items_str;
-    };
-
-    if name.ends_with(['s', 'x', 'y']) {
-        // Given a type called e.g. "Boss", "Fox" or "Story", don't try to
-        // create a plural.
-        items_str
-    } else {
-        SmolStr::new(format!("{name}s"))
-    }
-}
-
 fn trait_name(trait_: &hir::Trait, db: &RootDatabase, edition: Edition) -> Option<String> {
     let name = trait_.name(db).display(db, edition).to_string();
     if USELESS_TRAITS.contains(&name.as_str()) {
@@ -928,58 +897,6 @@ fn foo() { $0(bar())$0; }
         );
     }
 
-    #[test]
-    fn vec_value() {
-        check(
-            r#"
-struct Vec<T> {};
-struct Seed;
-fn bar() -> Vec<Seed> {}
-fn foo() { $0(bar())$0; }
-"#,
-            "seeds",
-        );
-    }
-
-    #[test]
-    fn vec_value_ends_with_s() {
-        check(
-            r#"
-struct Vec<T> {};
-struct Boss;
-fn bar() -> Vec<Boss> {}
-fn foo() { $0(bar())$0; }
-"#,
-            "items",
-        );
-    }
-
-    #[test]
-    fn vecdeque_value() {
-        check(
-            r#"
-struct VecDeque<T> {};
-struct Seed;
-fn bar() -> VecDeque<Seed> {}
-fn foo() { $0(bar())$0; }
-"#,
-            "seeds",
-        );
-    }
-
-    #[test]
-    fn slice_value() {
-        check(
-            r#"
-struct Vec<T> {};
-struct Seed;
-fn bar() -> &[Seed] {}
-fn foo() { $0(bar())$0; }
-"#,
-            "seeds",
-        );
-    }
-
     #[test]
     fn ref_call() {
         check(
diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs
index 40f3406b72..46242b75dd 100644
--- a/crates/ide/src/hover/render.rs
+++ b/crates/ide/src/hover/render.rs
@@ -1082,19 +1082,7 @@ fn render_memory_layout(
 
     if config.niches {
         if let Some(niches) = layout.niches() {
-            if niches > 1024 {
-                if niches.is_power_of_two() {
-                    format_to!(label, "niches = 2{}, ", pwr2_to_exponent(niches));
-                } else if is_pwr2plus1(niches) {
-                    format_to!(label, "niches = 2{} + 1, ", pwr2_to_exponent(niches - 1));
-                } else if is_pwr2minus1(niches) {
-                    format_to!(label, "niches = 2{} - 1, ", pwr2_to_exponent(niches + 1));
-                } else {
-                    format_to!(label, "niches = a lot, ");
-                }
-            } else {
-                format_to!(label, "niches = {niches}, ");
-            }
+            format_to!(label, "niches = {niches}, ");
         }
     }
     label.pop(); // ' '
@@ -1222,74 +1210,3 @@ fn render_dyn_compatibility(
         }
     }
 }
-
-fn is_pwr2minus1(val: u128) -> bool {
-    val == u128::MAX || (val + 1).is_power_of_two()
-}
-
-fn is_pwr2plus1(val: u128) -> bool {
-    val != 0 && (val - 1).is_power_of_two()
-}
-
-/// Formats a power of two as an exponent of two, i.e. 16 => ⁴. Note that `num` MUST be a power
-/// of 2, or this function will panic.
-fn pwr2_to_exponent(num: u128) -> String {
-    const DIGITS: [char; 10] = ['⁰', '¹', '²', '³', '⁴', '⁵', '⁶', '⁷', '⁸', '⁹'];
-    assert_eq!(num.count_ones(), 1);
-    num.trailing_zeros()
-        .to_string()
-        .chars()
-        .map(|c| c.to_digit(10).unwrap() as usize)
-        .map(|idx| DIGITS[idx])
-        .collect::<String>()
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    const TESTERS: [u128; 10] = [0, 1, 2, 3, 4, 255, 256, 257, u128::MAX - 1, u128::MAX];
-
-    #[test]
-    fn test_is_pwr2minus1() {
-        const OUTCOMES: [bool; 10] =
-            [true, true, false, true, false, true, false, false, false, true];
-        for (test, expected) in TESTERS.iter().zip(OUTCOMES) {
-            let actual = is_pwr2minus1(*test);
-            assert_eq!(actual, expected, "is_pwr2minu1({test}) gave {actual}, expected {expected}");
-        }
-    }
-
-    #[test]
-    fn test_is_pwr2plus1() {
-        const OUTCOMES: [bool; 10] =
-            [false, false, true, true, false, false, false, true, false, false];
-        for (test, expected) in TESTERS.iter().zip(OUTCOMES) {
-            let actual = is_pwr2plus1(*test);
-            assert_eq!(actual, expected, "is_pwr2plus1({test}) gave {actual}, expected {expected}");
-        }
-    }
-
-    #[test]
-    fn test_pwr2_to_exponent() {
-        const TESTERS: [u128; 9] = [
-            1,
-            2,
-            4,
-            8,
-            16,
-            9223372036854775808,
-            18446744073709551616,
-            36893488147419103232,
-            170141183460469231731687303715884105728,
-        ];
-        const OUTCOMES: [&str; 9] = ["⁰", "¹", "²", "³", "⁴", "⁶³", "⁶⁴", "⁶⁵", "¹²⁷"];
-        for (test, expected) in TESTERS.iter().zip(OUTCOMES) {
-            let actual = pwr2_to_exponent(*test);
-            assert_eq!(
-                actual, expected,
-                "pwr2_to_exponent({test}) returned {actual}, expected {expected}",
-            );
-        }
-    }
-}
diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs
index 1f723c85df..6d83a747d7 100644
--- a/crates/ide/src/inlay_hints.rs
+++ b/crates/ide/src/inlay_hints.rs
@@ -209,7 +209,7 @@ fn hints(
 ) {
     closing_brace::hints(hints, sema, config, file_id, node.clone());
     if let Some(any_has_generic_args) = ast::AnyHasGenericArgs::cast(node.clone()) {
-        generic_param::hints(hints, famous_defs, config, any_has_generic_args);
+        generic_param::hints(hints, sema, config, any_has_generic_args);
     }
 
     match_ast! {
@@ -300,23 +300,22 @@ pub struct InlayHintsConfig {
     pub closing_brace_hints_min_lines: Option<usize>,
     pub fields_to_resolve: InlayFieldsToResolve,
 }
-
 impl InlayHintsConfig {
-    fn lazy_text_edit(&self, finish: impl FnOnce() -> TextEdit) -> LazyProperty<TextEdit> {
+    fn lazy_text_edit(&self, finish: impl FnOnce() -> TextEdit) -> Lazy<TextEdit> {
         if self.fields_to_resolve.resolve_text_edits {
-            LazyProperty::Lazy
+            Lazy::Lazy
         } else {
             let edit = finish();
             never!(edit.is_empty(), "inlay hint produced an empty text edit");
-            LazyProperty::Computed(edit)
+            Lazy::Computed(edit)
         }
     }
 
-    fn lazy_tooltip(&self, finish: impl FnOnce() -> InlayTooltip) -> LazyProperty<InlayTooltip> {
+    fn lazy_tooltip(&self, finish: impl FnOnce() -> InlayTooltip) -> Lazy<InlayTooltip> {
         if self.fields_to_resolve.resolve_hint_tooltip
             && self.fields_to_resolve.resolve_label_tooltip
         {
-            LazyProperty::Lazy
+            Lazy::Lazy
         } else {
             let tooltip = finish();
             never!(
@@ -327,20 +326,7 @@ impl InlayHintsConfig {
                 .is_empty(),
                 "inlay hint produced an empty tooltip"
             );
-            LazyProperty::Computed(tooltip)
-        }
-    }
-
-    /// This always reports a resolvable location, so only use this when it is very likely for a
-    /// location link to actually resolve but where computing `finish` would be costly.
-    fn lazy_location_opt(
-        &self,
-        finish: impl FnOnce() -> Option<FileRange>,
-    ) -> Option<LazyProperty<FileRange>> {
-        if self.fields_to_resolve.resolve_label_location {
-            Some(LazyProperty::Lazy)
-        } else {
-            finish().map(LazyProperty::Computed)
+            Lazy::Computed(tooltip)
         }
     }
 }
@@ -455,7 +441,7 @@ pub struct InlayHint {
     /// The actual label to show in the inlay hint.
     pub label: InlayHintLabel,
     /// Text edit to apply when "accepting" this inlay hint.
-    pub text_edit: Option<LazyProperty<TextEdit>>,
+    pub text_edit: Option<Lazy<TextEdit>>,
     /// Range to recompute inlay hints when trying to resolve for this hint. If this is none, the
     /// hint does not support resolving.
     pub resolve_parent: Option<TextRange>,
@@ -463,15 +449,15 @@ pub struct InlayHint {
 
 /// A type signaling that a value is either computed, or is available for computation.
 #[derive(Clone, Debug)]
-pub enum LazyProperty<T> {
+pub enum Lazy<T> {
     Computed(T),
     Lazy,
 }
 
-impl<T> LazyProperty<T> {
+impl<T> Lazy<T> {
     pub fn computed(self) -> Option<T> {
         match self {
-            LazyProperty::Computed(it) => Some(it),
+            Lazy::Computed(it) => Some(it),
             _ => None,
         }
     }
@@ -522,8 +508,8 @@ pub struct InlayHintLabel {
 impl InlayHintLabel {
     pub fn simple(
         s: impl Into<String>,
-        tooltip: Option<LazyProperty<InlayTooltip>>,
-        linked_location: Option<LazyProperty<FileRange>>,
+        tooltip: Option<Lazy<InlayTooltip>>,
+        linked_location: Option<FileRange>,
     ) -> InlayHintLabel {
         InlayHintLabel {
             parts: smallvec![InlayHintLabelPart { text: s.into(), linked_location, tooltip }],
@@ -607,16 +593,16 @@ pub struct InlayHintLabelPart {
     /// refers to (not necessarily the location itself).
     /// When setting this, no tooltip must be set on the containing hint, or VS Code will display
     /// them both.
-    pub linked_location: Option<LazyProperty<FileRange>>,
+    pub linked_location: Option<FileRange>,
     /// The tooltip to show when hovering over the inlay hint, this may invoke other actions like
     /// hover requests to show.
-    pub tooltip: Option<LazyProperty<InlayTooltip>>,
+    pub tooltip: Option<Lazy<InlayTooltip>>,
 }
 
 impl std::hash::Hash for InlayHintLabelPart {
     fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
         self.text.hash(state);
-        self.linked_location.is_some().hash(state);
+        self.linked_location.hash(state);
         self.tooltip.is_some().hash(state);
     }
 }
@@ -624,9 +610,7 @@ impl std::hash::Hash for InlayHintLabelPart {
 impl fmt::Debug for InlayHintLabelPart {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
-            Self { text, linked_location: None, tooltip: None | Some(LazyProperty::Lazy) } => {
-                text.fmt(f)
-            }
+            Self { text, linked_location: None, tooltip: None | Some(Lazy::Lazy) } => text.fmt(f),
             Self { text, linked_location, tooltip } => f
                 .debug_struct("InlayHintLabelPart")
                 .field("text", text)
@@ -634,10 +618,8 @@ impl fmt::Debug for InlayHintLabelPart {
                 .field(
                     "tooltip",
                     &tooltip.as_ref().map_or("", |it| match it {
-                        LazyProperty::Computed(
-                            InlayTooltip::String(it) | InlayTooltip::Markdown(it),
-                        ) => it,
-                        LazyProperty::Lazy => "",
+                        Lazy::Computed(InlayTooltip::String(it) | InlayTooltip::Markdown(it)) => it,
+                        Lazy::Lazy => "",
                     }),
                 )
                 .finish(),
@@ -650,8 +632,7 @@ struct InlayHintLabelBuilder<'a> {
     db: &'a RootDatabase,
     result: InlayHintLabel,
     last_part: String,
-    resolve: bool,
-    location: Option<LazyProperty<FileRange>>,
+    location: Option<FileRange>,
 }
 
 impl fmt::Write for InlayHintLabelBuilder<'_> {
@@ -664,16 +645,11 @@ impl HirWrite for InlayHintLabelBuilder<'_> {
     fn start_location_link(&mut self, def: ModuleDefId) {
         never!(self.location.is_some(), "location link is already started");
         self.make_new_part();
-
-        self.location = Some(if self.resolve {
-            LazyProperty::Lazy
-        } else {
-            LazyProperty::Computed({
-                let Some(location) = ModuleDef::from(def).try_to_nav(self.db) else { return };
-                let location = location.call_site();
-                FileRange { file_id: location.file_id, range: location.focus_or_full_range() }
-            })
-        });
+        let Some(location) = ModuleDef::from(def).try_to_nav(self.db) else { return };
+        let location = location.call_site();
+        let location =
+            FileRange { file_id: location.file_id, range: location.focus_or_full_range() };
+        self.location = Some(location);
     }
 
     fn end_location_link(&mut self) {
@@ -759,7 +735,6 @@ fn label_of_ty(
         last_part: String::new(),
         location: None,
         result: InlayHintLabel::default(),
-        resolve: config.fields_to_resolve.resolve_label_location,
     };
     let _ = rec(sema, famous_defs, config.max_length, ty, &mut label_builder, config, edition);
     let r = label_builder.finish();
@@ -808,7 +783,7 @@ fn ty_to_text_edit(
     ty: &hir::Type,
     offset_to_insert: TextSize,
     prefix: impl Into<String>,
-) -> Option<LazyProperty<TextEdit>> {
+) -> Option<Lazy<TextEdit>> {
     // FIXME: Limit the length and bail out on excess somehow?
     let rendered = sema
         .scope(node_for_hint)
diff --git a/crates/ide/src/inlay_hints/bounds.rs b/crates/ide/src/inlay_hints/bounds.rs
index e9b728bcaa..429ddd31cb 100644
--- a/crates/ide/src/inlay_hints/bounds.rs
+++ b/crates/ide/src/inlay_hints/bounds.rs
@@ -22,7 +22,11 @@ pub(super) fn hints(
         return None;
     }
 
-    let sized_trait = famous_defs.core_marker_Sized();
+    let linked_location =
+        famous_defs.core_marker_Sized().and_then(|it| it.try_to_nav(sema.db)).map(|it| {
+            let n = it.call_site();
+            FileRange { file_id: n.file_id, range: n.focus_or_full_range() }
+        });
 
     for param in params.type_or_const_params() {
         match param {
@@ -44,17 +48,7 @@ pub(super) fn hints(
                         }
                         hint.parts.push(InlayHintLabelPart {
                             text: "Sized".to_owned(),
-                            linked_location: sized_trait.and_then(|it| {
-                                config.lazy_location_opt(|| {
-                                    it.try_to_nav(sema.db).map(|it| {
-                                        let n = it.call_site();
-                                        FileRange {
-                                            file_id: n.file_id,
-                                            range: n.focus_or_full_range(),
-                                        }
-                                    })
-                                })
-                            }),
+                            linked_location,
                             tooltip: None,
                         });
                         if has_bounds {
@@ -140,14 +134,12 @@ fn foo<T>() {}
                             InlayHintLabelPart {
                                 text: "Sized",
                                 linked_location: Some(
-                                    Computed(
-                                        FileRangeWrapper {
-                                            file_id: FileId(
-                                                1,
-                                            ),
-                                            range: 135..140,
-                                        },
-                                    ),
+                                    FileRangeWrapper {
+                                        file_id: FileId(
+                                            1,
+                                        ),
+                                        range: 135..140,
+                                    },
                                 ),
                                 tooltip: "",
                             },
diff --git a/crates/ide/src/inlay_hints/chaining.rs b/crates/ide/src/inlay_hints/chaining.rs
index 8471547727..7fa7ab1a94 100644
--- a/crates/ide/src/inlay_hints/chaining.rs
+++ b/crates/ide/src/inlay_hints/chaining.rs
@@ -81,10 +81,7 @@ mod tests {
 
     use crate::{
         fixture,
-        inlay_hints::{
-            tests::{check_expect, check_with_config, DISABLED_CONFIG, TEST_CONFIG},
-            LazyProperty,
-        },
+        inlay_hints::tests::{check_expect, check_with_config, DISABLED_CONFIG, TEST_CONFIG},
         InlayHintsConfig,
     };
 
@@ -102,7 +99,7 @@ mod tests {
         let (analysis, file_id) = fixture::file(ra_fixture);
         let mut inlay_hints = analysis.inlay_hints(&config, file_id, None).unwrap();
         inlay_hints.iter_mut().flat_map(|hint| &mut hint.label.parts).for_each(|hint| {
-            if let Some(LazyProperty::Computed(loc)) = &mut hint.linked_location {
+            if let Some(loc) = &mut hint.linked_location {
                 loc.range = TextRange::empty(TextSize::from(0));
             }
         });
@@ -137,14 +134,12 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "B",
                                 linked_location: Some(
-                                    Computed(
-                                        FileRangeWrapper {
-                                            file_id: FileId(
-                                                0,
-                                            ),
-                                            range: 63..64,
-                                        },
-                                    ),
+                                    FileRangeWrapper {
+                                        file_id: FileId(
+                                            0,
+                                        ),
+                                        range: 63..64,
+                                    },
                                 ),
                                 tooltip: "",
                             },
@@ -156,14 +151,12 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "A",
                                 linked_location: Some(
-                                    Computed(
-                                        FileRangeWrapper {
-                                            file_id: FileId(
-                                                0,
-                                            ),
-                                            range: 7..8,
-                                        },
-                                    ),
+                                    FileRangeWrapper {
+                                        file_id: FileId(
+                                            0,
+                                        ),
+                                        range: 7..8,
+                                    },
                                 ),
                                 tooltip: "",
                             },
@@ -220,14 +213,12 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "C",
                                 linked_location: Some(
-                                    Computed(
-                                        FileRangeWrapper {
-                                            file_id: FileId(
-                                                0,
-                                            ),
-                                            range: 51..52,
-                                        },
-                                    ),
+                                    FileRangeWrapper {
+                                        file_id: FileId(
+                                            0,
+                                        ),
+                                        range: 51..52,
+                                    },
                                 ),
                                 tooltip: "",
                             },
@@ -239,14 +230,12 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "B",
                                 linked_location: Some(
-                                    Computed(
-                                        FileRangeWrapper {
-                                            file_id: FileId(
-                                                0,
-                                            ),
-                                            range: 29..30,
-                                        },
-                                    ),
+                                    FileRangeWrapper {
+                                        file_id: FileId(
+                                            0,
+                                        ),
+                                        range: 29..30,
+                                    },
                                 ),
                                 tooltip: "",
                             },
@@ -287,14 +276,12 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "C",
                                 linked_location: Some(
-                                    Computed(
-                                        FileRangeWrapper {
-                                            file_id: FileId(
-                                                0,
-                                            ),
-                                            range: 51..52,
-                                        },
-                                    ),
+                                    FileRangeWrapper {
+                                        file_id: FileId(
+                                            0,
+                                        ),
+                                        range: 51..52,
+                                    },
                                 ),
                                 tooltip: "",
                             },
@@ -306,14 +293,12 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "B",
                                 linked_location: Some(
-                                    Computed(
-                                        FileRangeWrapper {
-                                            file_id: FileId(
-                                                0,
-                                            ),
-                                            range: 29..30,
-                                        },
-                                    ),
+                                    FileRangeWrapper {
+                                        file_id: FileId(
+                                            0,
+                                        ),
+                                        range: 29..30,
+                                    },
                                 ),
                                 tooltip: "",
                             },
@@ -355,14 +340,12 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "B",
                                 linked_location: Some(
-                                    Computed(
-                                        FileRangeWrapper {
-                                            file_id: FileId(
-                                                0,
-                                            ),
-                                            range: 23..24,
-                                        },
-                                    ),
+                                    FileRangeWrapper {
+                                        file_id: FileId(
+                                            0,
+                                        ),
+                                        range: 23..24,
+                                    },
                                 ),
                                 tooltip: "",
                             },
@@ -370,14 +353,12 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "X",
                                 linked_location: Some(
-                                    Computed(
-                                        FileRangeWrapper {
-                                            file_id: FileId(
-                                                0,
-                                            ),
-                                            range: 55..56,
-                                        },
-                                    ),
+                                    FileRangeWrapper {
+                                        file_id: FileId(
+                                            0,
+                                        ),
+                                        range: 55..56,
+                                    },
                                 ),
                                 tooltip: "",
                             },
@@ -390,14 +371,12 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "A",
                                 linked_location: Some(
-                                    Computed(
-                                        FileRangeWrapper {
-                                            file_id: FileId(
-                                                0,
-                                            ),
-                                            range: 7..8,
-                                        },
-                                    ),
+                                    FileRangeWrapper {
+                                        file_id: FileId(
+                                            0,
+                                        ),
+                                        range: 7..8,
+                                    },
                                 ),
                                 tooltip: "",
                             },
@@ -405,14 +384,12 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "X",
                                 linked_location: Some(
-                                    Computed(
-                                        FileRangeWrapper {
-                                            file_id: FileId(
-                                                0,
-                                            ),
-                                            range: 55..56,
-                                        },
-                                    ),
+                                    FileRangeWrapper {
+                                        file_id: FileId(
+                                            0,
+                                        ),
+                                        range: 55..56,
+                                    },
                                 ),
                                 tooltip: "",
                             },
@@ -458,14 +435,12 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "Iterator",
                                 linked_location: Some(
-                                    Computed(
-                                        FileRangeWrapper {
-                                            file_id: FileId(
-                                                1,
-                                            ),
-                                            range: 0..0,
-                                        },
-                                    ),
+                                    FileRangeWrapper {
+                                        file_id: FileId(
+                                            1,
+                                        ),
+                                        range: 0..0,
+                                    },
                                 ),
                                 tooltip: "",
                             },
@@ -473,14 +448,12 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "Item",
                                 linked_location: Some(
-                                    Computed(
-                                        FileRangeWrapper {
-                                            file_id: FileId(
-                                                1,
-                                            ),
-                                            range: 0..0,
-                                        },
-                                    ),
+                                    FileRangeWrapper {
+                                        file_id: FileId(
+                                            1,
+                                        ),
+                                        range: 0..0,
+                                    },
                                 ),
                                 tooltip: "",
                             },
@@ -494,14 +467,12 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "Iterator",
                                 linked_location: Some(
-                                    Computed(
-                                        FileRangeWrapper {
-                                            file_id: FileId(
-                                                1,
-                                            ),
-                                            range: 0..0,
-                                        },
-                                    ),
+                                    FileRangeWrapper {
+                                        file_id: FileId(
+                                            1,
+                                        ),
+                                        range: 0..0,
+                                    },
                                 ),
                                 tooltip: "",
                             },
@@ -509,14 +480,12 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "Item",
                                 linked_location: Some(
-                                    Computed(
-                                        FileRangeWrapper {
-                                            file_id: FileId(
-                                                1,
-                                            ),
-                                            range: 0..0,
-                                        },
-                                    ),
+                                    FileRangeWrapper {
+                                        file_id: FileId(
+                                            1,
+                                        ),
+                                        range: 0..0,
+                                    },
                                 ),
                                 tooltip: "",
                             },
@@ -530,14 +499,12 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "Iterator",
                                 linked_location: Some(
-                                    Computed(
-                                        FileRangeWrapper {
-                                            file_id: FileId(
-                                                1,
-                                            ),
-                                            range: 0..0,
-                                        },
-                                    ),
+                                    FileRangeWrapper {
+                                        file_id: FileId(
+                                            1,
+                                        ),
+                                        range: 0..0,
+                                    },
                                 ),
                                 tooltip: "",
                             },
@@ -545,14 +512,12 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "Item",
                                 linked_location: Some(
-                                    Computed(
-                                        FileRangeWrapper {
-                                            file_id: FileId(
-                                                1,
-                                            ),
-                                            range: 0..0,
-                                        },
-                                    ),
+                                    FileRangeWrapper {
+                                        file_id: FileId(
+                                            1,
+                                        ),
+                                        range: 0..0,
+                                    },
                                 ),
                                 tooltip: "",
                             },
@@ -566,14 +531,12 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "MyIter",
                                 linked_location: Some(
-                                    Computed(
-                                        FileRangeWrapper {
-                                            file_id: FileId(
-                                                0,
-                                            ),
-                                            range: 0..0,
-                                        },
-                                    ),
+                                    FileRangeWrapper {
+                                        file_id: FileId(
+                                            0,
+                                        ),
+                                        range: 0..0,
+                                    },
                                 ),
                                 tooltip: "",
                             },
@@ -614,14 +577,12 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "Struct",
                                 linked_location: Some(
-                                    Computed(
-                                        FileRangeWrapper {
-                                            file_id: FileId(
-                                                0,
-                                            ),
-                                            range: 7..13,
-                                        },
-                                    ),
+                                    FileRangeWrapper {
+                                        file_id: FileId(
+                                            0,
+                                        ),
+                                        range: 7..13,
+                                    },
                                 ),
                                 tooltip: "",
                             },
@@ -633,14 +594,12 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "Struct",
                                 linked_location: Some(
-                                    Computed(
-                                        FileRangeWrapper {
-                                            file_id: FileId(
-                                                0,
-                                            ),
-                                            range: 7..13,
-                                        },
-                                    ),
+                                    FileRangeWrapper {
+                                        file_id: FileId(
+                                            0,
+                                        ),
+                                        range: 7..13,
+                                    },
                                 ),
                                 tooltip: "",
                             },
@@ -652,14 +611,12 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "Struct",
                                 linked_location: Some(
-                                    Computed(
-                                        FileRangeWrapper {
-                                            file_id: FileId(
-                                                0,
-                                            ),
-                                            range: 7..13,
-                                        },
-                                    ),
+                                    FileRangeWrapper {
+                                        file_id: FileId(
+                                            0,
+                                        ),
+                                        range: 7..13,
+                                    },
                                 ),
                                 tooltip: "",
                             },
@@ -671,14 +628,12 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "self",
                                 linked_location: Some(
-                                    Computed(
-                                        FileRangeWrapper {
-                                            file_id: FileId(
-                                                0,
-                                            ),
-                                            range: 42..46,
-                                        },
-                                    ),
+                                    FileRangeWrapper {
+                                        file_id: FileId(
+                                            0,
+                                        ),
+                                        range: 42..46,
+                                    },
                                 ),
                                 tooltip: "",
                             },
diff --git a/crates/ide/src/inlay_hints/closing_brace.rs b/crates/ide/src/inlay_hints/closing_brace.rs
index 3767d34e2c..90b8be64a4 100644
--- a/crates/ide/src/inlay_hints/closing_brace.rs
+++ b/crates/ide/src/inlay_hints/closing_brace.rs
@@ -11,10 +11,7 @@ use syntax::{
     match_ast, SyntaxKind, SyntaxNode, T,
 };
 
-use crate::{
-    inlay_hints::LazyProperty, InlayHint, InlayHintLabel, InlayHintPosition, InlayHintsConfig,
-    InlayKind,
-};
+use crate::{InlayHint, InlayHintLabel, InlayHintPosition, InlayHintsConfig, InlayKind};
 
 pub(super) fn hints(
     acc: &mut Vec<InlayHint>,
@@ -144,7 +141,7 @@ pub(super) fn hints(
     acc.push(InlayHint {
         range: closing_token.text_range(),
         kind: InlayKind::ClosingBrace,
-        label: InlayHintLabel::simple(label, None, linked_location.map(LazyProperty::Computed)),
+        label: InlayHintLabel::simple(label, None, linked_location),
         text_edit: None,
         position: InlayHintPosition::After,
         pad_left: true,
diff --git a/crates/ide/src/inlay_hints/closure_captures.rs b/crates/ide/src/inlay_hints/closure_captures.rs
index 3e91618d08..906f2acf0c 100644
--- a/crates/ide/src/inlay_hints/closure_captures.rs
+++ b/crates/ide/src/inlay_hints/closure_captures.rs
@@ -53,6 +53,10 @@ pub(super) fn hints(
     let last = captures.len() - 1;
     for (idx, capture) in captures.into_iter().enumerate() {
         let local = capture.local();
+        let source = local.primary_source(sema.db);
+
+        // force cache the source file, otherwise sema lookup will potentially panic
+        _ = sema.parse_or_expand(source.file());
 
         let label = format!(
             "{}{}",
@@ -69,17 +73,8 @@ pub(super) fn hints(
         }
         hint.label.append_part(InlayHintLabelPart {
             text: label,
-            linked_location: config.lazy_location_opt(|| {
-                let source = local.primary_source(sema.db);
-
-                // force cache the source file, otherwise sema lookup will potentially panic
-                _ = sema.parse_or_expand(source.file());
-                source.name().and_then(|name| {
-                    name.syntax()
-                        .original_file_range_opt(sema.db)
-                        .map(TupleExt::head)
-                        .map(Into::into)
-                })
+            linked_location: source.name().and_then(|name| {
+                name.syntax().original_file_range_opt(sema.db).map(TupleExt::head).map(Into::into)
             }),
             tooltip: None,
         });
diff --git a/crates/ide/src/inlay_hints/generic_param.rs b/crates/ide/src/inlay_hints/generic_param.rs
index 762a4c2655..037b328d97 100644
--- a/crates/ide/src/inlay_hints/generic_param.rs
+++ b/crates/ide/src/inlay_hints/generic_param.rs
@@ -1,19 +1,17 @@
 //! Implementation of inlay hints for generic parameters.
-use ide_db::{active_parameter::generic_def_for_node, famous_defs::FamousDefs};
+use ide_db::{active_parameter::generic_def_for_node, RootDatabase};
 use syntax::{
     ast::{self, AnyHasGenericArgs, HasGenericArgs, HasName},
     AstNode,
 };
 
-use crate::{
-    inlay_hints::GenericParameterHints, InlayHint, InlayHintLabel, InlayHintsConfig, InlayKind,
-};
+use crate::{inlay_hints::GenericParameterHints, InlayHint, InlayHintsConfig, InlayKind};
 
-use super::param_name::is_argument_similar_to_param_name;
+use super::param_name::{is_argument_similar_to_param_name, render_label};
 
 pub(crate) fn hints(
     acc: &mut Vec<InlayHint>,
-    FamousDefs(sema, krate): &FamousDefs<'_, '_>,
+    sema: &hir::Semantics<'_, RootDatabase>,
     config: &InlayHintsConfig,
     node: AnyHasGenericArgs,
 ) -> Option<()> {
@@ -47,23 +45,12 @@ pub(crate) fn hints(
             return None;
         }
 
-        let allowed = match (param, &arg) {
-            (hir::GenericParam::TypeParam(_), ast::GenericArg::TypeArg(_)) => type_hints,
-            (hir::GenericParam::ConstParam(_), ast::GenericArg::ConstArg(_)) => const_hints,
-            (hir::GenericParam::LifetimeParam(_), ast::GenericArg::LifetimeArg(_)) => {
-                lifetime_hints
-            }
-            _ => false,
-        };
-        if !allowed {
-            return None;
-        }
-
-        let param_name = param.name(sema.db);
+        let name = param.name(sema.db);
+        let param_name = name.as_str();
 
         let should_hide = {
             let argument = get_string_representation(&arg)?;
-            is_argument_similar_to_param_name(&argument, param_name.as_str())
+            is_argument_similar_to_param_name(&argument, param_name)
         };
 
         if should_hide {
@@ -72,28 +59,30 @@ pub(crate) fn hints(
 
         let range = sema.original_range_opt(arg.syntax())?.range;
 
-        let colon = if config.render_colons { ":" } else { "" };
-        let label = InlayHintLabel::simple(
-            format!("{}{colon}", param_name.display(sema.db, krate.edition(sema.db))),
-            None,
-            config.lazy_location_opt(|| {
-                let source_syntax = match param {
-                    hir::GenericParam::TypeParam(it) => {
-                        sema.source(it.merge()).map(|it| it.value.syntax().clone())
-                    }
-                    hir::GenericParam::ConstParam(it) => {
-                        let syntax = sema.source(it.merge())?.value.syntax().clone();
-                        let const_param = ast::ConstParam::cast(syntax)?;
-                        const_param.name().map(|it| it.syntax().clone())
-                    }
-                    hir::GenericParam::LifetimeParam(it) => {
-                        sema.source(it).map(|it| it.value.syntax().clone())
-                    }
-                };
-                let linked_location = source_syntax.and_then(|it| sema.original_range_opt(&it));
-                linked_location.map(Into::into)
-            }),
-        );
+        let source_syntax = match param {
+            hir::GenericParam::TypeParam(it) => {
+                if !type_hints || !matches!(arg, ast::GenericArg::TypeArg(_)) {
+                    return None;
+                }
+                sema.source(it.merge())?.value.syntax().clone()
+            }
+            hir::GenericParam::ConstParam(it) => {
+                if !const_hints || !matches!(arg, ast::GenericArg::ConstArg(_)) {
+                    return None;
+                }
+                let syntax = sema.source(it.merge())?.value.syntax().clone();
+                let const_param = ast::ConstParam::cast(syntax)?;
+                const_param.name()?.syntax().clone()
+            }
+            hir::GenericParam::LifetimeParam(it) => {
+                if !lifetime_hints || !matches!(arg, ast::GenericArg::LifetimeArg(_)) {
+                    return None;
+                }
+                sema.source(it)?.value.syntax().clone()
+            }
+        };
+        let linked_location = sema.original_range_opt(&source_syntax);
+        let label = render_label(param_name, config, linked_location);
 
         Some(InlayHint {
             range,
diff --git a/crates/ide/src/inlay_hints/implicit_drop.rs b/crates/ide/src/inlay_hints/implicit_drop.rs
index 27c7c3d498..1358d3722f 100644
--- a/crates/ide/src/inlay_hints/implicit_drop.rs
+++ b/crates/ide/src/inlay_hints/implicit_drop.rs
@@ -49,7 +49,7 @@ pub(super) fn hints(
             if mir.locals[place.local].ty.adt_id(ChalkTyInterner).is_none() {
                 continue; // Arguably only ADTs have significant drop impls
             }
-            let Some(&binding_idx) = local_to_binding.get(place.local) else {
+            let Some(binding) = local_to_binding.get(place.local) else {
                 continue; // Ignore temporary values
             };
             let range = match terminator.span {
@@ -91,26 +91,25 @@ pub(super) fn hints(
                 },
                 MirSpan::Unknown => continue,
             };
-            let binding = &hir.bindings[binding_idx];
+            let binding_source = source_map
+                .patterns_for_binding(*binding)
+                .first()
+                .and_then(|d| source_map.pat_syntax(*d).ok())
+                .and_then(|d| {
+                    Some(FileRange {
+                        file_id: d.file_id.file_id()?.into(),
+                        range: d.value.text_range(),
+                    })
+                });
+            let binding = &hir.bindings[*binding];
             let name = binding.name.display_no_db(file_id.edition()).to_smolstr();
             if name.starts_with("<ra@") {
                 continue; // Ignore desugared variables
             }
             let mut label = InlayHintLabel::simple(
                 name,
-                None,
-                config.lazy_location_opt(|| {
-                    source_map
-                        .patterns_for_binding(binding_idx)
-                        .first()
-                        .and_then(|d| source_map.pat_syntax(*d).ok())
-                        .and_then(|d| {
-                            Some(FileRange {
-                                file_id: d.file_id.file_id()?.into(),
-                                range: d.value.text_range(),
-                            })
-                        })
-                }),
+                Some(config.lazy_tooltip(|| crate::InlayTooltip::String("moz".into()))),
+                binding_source,
             );
             label.prepend_str("drop(");
             label.append_str(")");
diff --git a/crates/ide/src/inlay_hints/param_name.rs b/crates/ide/src/inlay_hints/param_name.rs
index 8f01b1bd38..a6f7e0c184 100644
--- a/crates/ide/src/inlay_hints/param_name.rs
+++ b/crates/ide/src/inlay_hints/param_name.rs
@@ -3,6 +3,7 @@
 //! fn max(x: i32, y: i32) -> i32 { x + y }
 //! _ = max(/*x*/4, /*y*/4);
 //! ```
+use std::fmt::Display;
 
 use either::Either;
 use hir::{Callable, Semantics};
@@ -19,7 +20,7 @@ use crate::{InlayHint, InlayHintLabel, InlayHintPosition, InlayHintsConfig, Inla
 
 pub(super) fn hints(
     acc: &mut Vec<InlayHint>,
-    FamousDefs(sema, krate): &FamousDefs<'_, '_>,
+    FamousDefs(sema, _): &FamousDefs<'_, '_>,
     config: &InlayHintsConfig,
     _file_id: EditionedFileId,
     expr: ast::Expr,
@@ -36,29 +37,23 @@ pub(super) fn hints(
         .filter_map(|(p, arg)| {
             // Only annotate hints for expressions that exist in the original file
             let range = sema.original_range_opt(arg.syntax())?;
-            let param_name = p.name(sema.db)?;
-            Some((p, param_name, arg, range))
+            let source = sema.source(p)?;
+            let (param_name, name_syntax) = match source.value.as_ref() {
+                Either::Left(pat) => (pat.name()?, pat.name()),
+                Either::Right(param) => match param.pat()? {
+                    ast::Pat::IdentPat(it) => (it.name()?, it.name()),
+                    _ => return None,
+                },
+            };
+            Some((name_syntax, param_name, arg, range))
         })
         .filter(|(_, param_name, arg, _)| {
-            !should_hide_param_name_hint(sema, &callable, param_name.as_str(), arg)
+            !should_hide_param_name_hint(sema, &callable, &param_name.text(), arg)
         })
         .map(|(param, param_name, _, hir::FileRange { range, .. })| {
-            let colon = if config.render_colons { ":" } else { "" };
-            let label = InlayHintLabel::simple(
-                format!("{}{colon}", param_name.display(sema.db, krate.edition(sema.db))),
-                None,
-                config.lazy_location_opt(|| {
-                    let source = sema.source(param)?;
-                    let name_syntax = match source.value.as_ref() {
-                        Either::Left(pat) => pat.name(),
-                        Either::Right(param) => match param.pat()? {
-                            ast::Pat::IdentPat(it) => it.name(),
-                            _ => None,
-                        },
-                    }?;
-                    sema.original_range_opt(name_syntax.syntax()).map(Into::into)
-                }),
-            );
+            let linked_location = param.and_then(|name| sema.original_range_opt(name.syntax()));
+
+            let label = render_label(&param_name, config, linked_location);
             InlayHint {
                 range,
                 kind: InlayKind::Parameter,
@@ -75,6 +70,16 @@ pub(super) fn hints(
     Some(())
 }
 
+pub(super) fn render_label(
+    param_name: impl Display,
+    config: &InlayHintsConfig,
+    linked_location: Option<hir::FileRange>,
+) -> InlayHintLabel {
+    let colon = if config.render_colons { ":" } else { "" };
+
+    InlayHintLabel::simple(format!("{param_name}{colon}"), None, linked_location.map(Into::into))
+}
+
 fn get_callable(
     sema: &Semantics<'_, RootDatabase>,
     expr: &ast::Expr,
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs
index 41a3302c09..346e2862b0 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -91,8 +91,7 @@ pub use crate::{
     inlay_hints::{
         AdjustmentHints, AdjustmentHintsMode, ClosureReturnTypeHints, DiscriminantHints,
         GenericParameterHints, InlayFieldsToResolve, InlayHint, InlayHintLabel, InlayHintLabelPart,
-        InlayHintPosition, InlayHintsConfig, InlayKind, InlayTooltip, LazyProperty,
-        LifetimeElisionHints,
+        InlayHintPosition, InlayHintsConfig, InlayKind, InlayTooltip, LifetimeElisionHints,
     },
     join_lines::JoinLinesConfig,
     markup::Markup,
diff --git a/crates/load-cargo/src/lib.rs b/crates/load-cargo/src/lib.rs
index 5654c04a59..00446b27cf 100644
--- a/crates/load-cargo/src/lib.rs
+++ b/crates/load-cargo/src/lib.rs
@@ -256,24 +256,6 @@ impl ProjectFolders {
             fsc.add_file_set(file_set_roots)
         }
 
-        for ws in workspaces.iter() {
-            let mut file_set_roots: Vec<VfsPath> = vec![];
-            let mut entries = vec![];
-
-            for buildfile in ws.buildfiles() {
-                file_set_roots.push(VfsPath::from(buildfile.to_owned()));
-                entries.push(buildfile.to_owned());
-            }
-
-            if !file_set_roots.is_empty() {
-                let entry = vfs::loader::Entry::Files(entries);
-                res.watch.push(res.load.len());
-                res.load.push(entry);
-                local_filesets.push(fsc.len() as u64);
-                fsc.add_file_set(file_set_roots)
-            }
-        }
-
         if let Some(user_config_path) = user_config_dir_path {
             let ratoml_path = {
                 let mut p = user_config_path.to_path_buf();
diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs
index dcd62753cb..f98d983ac0 100644
--- a/crates/project-model/src/workspace.rs
+++ b/crates/project-model/src/workspace.rs
@@ -524,17 +524,6 @@ impl ProjectWorkspace {
         }
     }
 
-    pub fn buildfiles(&self) -> Vec<AbsPathBuf> {
-        match &self.kind {
-            ProjectWorkspaceKind::Json(project) => project
-                .crates()
-                .filter_map(|(_, krate)| krate.build.as_ref().map(|build| build.build_file.clone()))
-                .map(|build_file| self.workspace_root().join(build_file))
-                .collect(),
-            _ => vec![],
-        }
-    }
-
     pub fn find_sysroot_proc_macro_srv(&self) -> anyhow::Result<AbsPathBuf> {
         self.sysroot.discover_proc_macro_srv()
     }
@@ -579,15 +568,27 @@ impl ProjectWorkspace {
         match &self.kind {
             ProjectWorkspaceKind::Json(project) => project
                 .crates()
-                .map(|(_, krate)| PackageRoot {
-                    is_local: krate.is_workspace_member,
-                    include: krate
-                        .include
-                        .iter()
-                        .cloned()
-                        .chain(self.extra_includes.iter().cloned())
-                        .collect(),
-                    exclude: krate.exclude.clone(),
+                .map(|(_, krate)| {
+                    // FIXME: PackageRoots dont allow specifying files, only directories
+                    let build_file = krate
+                        .build
+                        .as_ref()
+                        .map(|build| self.workspace_root().join(&build.build_file))
+                        .as_deref()
+                        .and_then(AbsPath::parent)
+                        .map(ToOwned::to_owned);
+
+                    PackageRoot {
+                        is_local: krate.is_workspace_member,
+                        include: krate
+                            .include
+                            .iter()
+                            .cloned()
+                            .chain(build_file)
+                            .chain(self.extra_includes.iter().cloned())
+                            .collect(),
+                        exclude: krate.exclude.clone(),
+                    }
                 })
                 .collect::<FxHashSet<_>>()
                 .into_iter()
diff --git a/crates/rust-analyzer/src/lsp/to_proto.rs b/crates/rust-analyzer/src/lsp/to_proto.rs
index 2a7d95d560..a5516e7f9d 100644
--- a/crates/rust-analyzer/src/lsp/to_proto.rs
+++ b/crates/rust-analyzer/src/lsp/to_proto.rs
@@ -11,8 +11,8 @@ use ide::{
     Annotation, AnnotationKind, Assist, AssistKind, Cancellable, CompletionFieldsToResolve,
     CompletionItem, CompletionItemKind, CompletionRelevance, Documentation, FileId, FileRange,
     FileSystemEdit, Fold, FoldKind, Highlight, HlMod, HlOperator, HlPunct, HlRange, HlTag, Indel,
-    InlayFieldsToResolve, InlayHint, InlayHintLabel, InlayHintLabelPart, InlayKind, LazyProperty,
-    Markup, NavigationTarget, ReferenceCategory, RenameError, Runnable, Severity, SignatureHelp,
+    InlayFieldsToResolve, InlayHint, InlayHintLabel, InlayHintLabelPart, InlayKind, Markup,
+    NavigationTarget, ReferenceCategory, RenameError, Runnable, Severity, SignatureHelp,
     SnippetEdit, SourceChange, StructureNodeKind, SymbolKind, TextEdit, TextRange, TextSize,
 };
 use ide_db::{assists, rust_doc::format_docs, FxHasher};
@@ -549,11 +549,12 @@ pub(crate) fn inlay_hint(
 ) -> Cancellable<lsp_types::InlayHint> {
     let hint_needs_resolve = |hint: &InlayHint| -> Option<TextRange> {
         hint.resolve_parent.filter(|_| {
-            hint.text_edit.as_ref().is_some_and(LazyProperty::is_lazy)
-                || hint.label.parts.iter().any(|part| {
-                    part.linked_location.as_ref().is_some_and(LazyProperty::is_lazy)
-                        || part.tooltip.as_ref().is_some_and(LazyProperty::is_lazy)
-                })
+            hint.text_edit.is_some()
+                || hint
+                    .label
+                    .parts
+                    .iter()
+                    .any(|part| part.linked_location.is_some() || part.tooltip.is_some())
         })
     };
 
@@ -568,21 +569,22 @@ pub(crate) fn inlay_hint(
     });
 
     let mut something_to_resolve = false;
-    let text_edits = inlay_hint
-        .text_edit
-        .take()
-        .and_then(|it| match it {
-            LazyProperty::Computed(it) => Some(it),
-            LazyProperty::Lazy => {
-                something_to_resolve |=
-                    snap.config.visual_studio_code_version().is_none_or(|version| {
-                        VersionReq::parse(">=1.86.0").unwrap().matches(version)
-                    }) && resolve_range_and_hash.is_some()
-                        && fields_to_resolve.resolve_text_edits;
-                None
-            }
-        })
-        .map(|it| text_edit_vec(line_index, it));
+    let text_edits = if snap
+        .config
+        .visual_studio_code_version()
+        .is_none_or(|version| VersionReq::parse(">=1.86.0").unwrap().matches(version))
+        && resolve_range_and_hash.is_some()
+        && fields_to_resolve.resolve_text_edits
+    {
+        something_to_resolve |= inlay_hint.text_edit.is_some();
+        None
+    } else {
+        inlay_hint
+            .text_edit
+            .take()
+            .and_then(|it| it.computed())
+            .map(|it| text_edit_vec(line_index, it))
+    };
     let (label, tooltip) = inlay_hint_label(
         snap,
         fields_to_resolve,
@@ -635,23 +637,22 @@ fn inlay_hint_label(
     let (label, tooltip) = match &*label.parts {
         [InlayHintLabelPart { linked_location: None, .. }] => {
             let InlayHintLabelPart { text, tooltip, .. } = label.parts.pop().unwrap();
-            let tooltip = tooltip.and_then(|it| match it {
-                LazyProperty::Computed(it) => Some(it),
-                LazyProperty::Lazy => {
-                    *something_to_resolve |=
-                        needs_resolve && fields_to_resolve.resolve_hint_tooltip;
-                    None
-                }
-            });
-            let hint_tooltip = match tooltip {
-                Some(ide::InlayTooltip::String(s)) => Some(lsp_types::InlayHintTooltip::String(s)),
-                Some(ide::InlayTooltip::Markdown(s)) => {
-                    Some(lsp_types::InlayHintTooltip::MarkupContent(lsp_types::MarkupContent {
-                        kind: lsp_types::MarkupKind::Markdown,
-                        value: s,
-                    }))
+            let hint_tooltip = if needs_resolve && fields_to_resolve.resolve_hint_tooltip {
+                *something_to_resolve |= tooltip.is_some();
+                None
+            } else {
+                match tooltip.and_then(|it| it.computed()) {
+                    Some(ide::InlayTooltip::String(s)) => {
+                        Some(lsp_types::InlayHintTooltip::String(s))
+                    }
+                    Some(ide::InlayTooltip::Markdown(s)) => {
+                        Some(lsp_types::InlayHintTooltip::MarkupContent(lsp_types::MarkupContent {
+                            kind: lsp_types::MarkupKind::Markdown,
+                            value: s,
+                        }))
+                    }
+                    None => None,
                 }
-                None => None,
             };
             (lsp_types::InlayHintLabel::String(text), hint_tooltip)
         }
@@ -660,38 +661,31 @@ fn inlay_hint_label(
                 .parts
                 .into_iter()
                 .map(|part| {
-                    let tooltip = part.tooltip.and_then(|it| match it {
-                        LazyProperty::Computed(it) => Some(it),
-                        LazyProperty::Lazy => {
-                            *something_to_resolve |= fields_to_resolve.resolve_label_tooltip;
-                            None
-                        }
-                    });
-                    let tooltip = match tooltip {
-                        Some(ide::InlayTooltip::String(s)) => {
-                            Some(lsp_types::InlayHintLabelPartTooltip::String(s))
-                        }
-                        Some(ide::InlayTooltip::Markdown(s)) => {
-                            Some(lsp_types::InlayHintLabelPartTooltip::MarkupContent(
-                                lsp_types::MarkupContent {
-                                    kind: lsp_types::MarkupKind::Markdown,
-                                    value: s,
-                                },
-                            ))
+                    let tooltip = if needs_resolve && fields_to_resolve.resolve_label_tooltip {
+                        *something_to_resolve |= part.tooltip.is_some();
+                        None
+                    } else {
+                        match part.tooltip.and_then(|it| it.computed()) {
+                            Some(ide::InlayTooltip::String(s)) => {
+                                Some(lsp_types::InlayHintLabelPartTooltip::String(s))
+                            }
+                            Some(ide::InlayTooltip::Markdown(s)) => {
+                                Some(lsp_types::InlayHintLabelPartTooltip::MarkupContent(
+                                    lsp_types::MarkupContent {
+                                        kind: lsp_types::MarkupKind::Markdown,
+                                        value: s,
+                                    },
+                                ))
+                            }
+                            None => None,
                         }
-                        None => None,
                     };
-                    let location = part
-                        .linked_location
-                        .and_then(|it| match it {
-                            LazyProperty::Computed(it) => Some(it),
-                            LazyProperty::Lazy => {
-                                *something_to_resolve |= fields_to_resolve.resolve_label_location;
-                                None
-                            }
-                        })
-                        .map(|range| location(snap, range))
-                        .transpose()?;
+                    let location = if needs_resolve && fields_to_resolve.resolve_label_location {
+                        *something_to_resolve |= part.linked_location.is_some();
+                        None
+                    } else {
+                        part.linked_location.map(|range| location(snap, range)).transpose()?
+                    };
                     Ok(lsp_types::InlayHintLabelPart {
                         value: part.text,
                         tooltip,


Test patch:
diff --git a/crates/ide-db/src/test_data/test_symbol_index_collection.txt b/crates/ide-db/src/test_data/test_symbol_index_collection.txt
index 535777dfcb..7dce95592b 100644
--- a/crates/ide-db/src/test_data/test_symbol_index_collection.txt
+++ b/crates/ide-db/src/test_data/test_symbol_index_collection.txt
@@ -1007,6 +1007,39 @@
                 is_alias: false,
                 is_assoc: false,
             },
+            FileSymbol {
+                name: "ThisStruct",
+                def: Adt(
+                    Struct(
+                        Struct {
+                            id: StructId(
+                                4,
+                            ),
+                        },
+                    ),
+                ),
+                loc: DeclarationLocation {
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            1,
+                        ),
+                        Edition2021,
+                    ),
+                    ptr: SyntaxNodePtr {
+                        kind: USE_TREE,
+                        range: 85..125,
+                    },
+                    name_ptr: AstPtr(
+                        SyntaxNodePtr {
+                            kind: NAME,
+                            range: 115..125,
+                        },
+                    ),
+                },
+                container_name: None,
+                is_alias: false,
+                is_assoc: false,
+            },
         ],
     ),
 ]
diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs
index 064a845dc5..014b751f95 100644
--- a/crates/ide/src/hover/tests.rs
+++ b/crates/ide/src/hover/tests.rs
@@ -1357,7 +1357,7 @@ fn hover_enum_limit() {
 
             ---
 
-            size = 12 (0xC), align = 4, niches = a lot
+            size = 12 (0xC), align = 4, niches = 4294967288
         "#]],
     );
 }