about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2023-08-16 11:18:11 +0200
committerLukas Wirth <lukastw97@gmail.com>2023-08-16 11:33:42 +0200
commitaf8048266cd87e7855cb150803260887aa93d01a (patch)
tree79aaa3b967e996fe6ceae0736479ec012afbfdf9
parent1b678231d71f48f078e1a80230c28a2fce2daec5 (diff)
downloadrust-af8048266cd87e7855cb150803260887aa93d01a.tar.gz
rust-af8048266cd87e7855cb150803260887aa93d01a.zip
Prepare ItemScope for IDE import resolution
-rw-r--r--crates/hir-def/src/find_path.rs18
-rw-r--r--crates/hir-def/src/import_map.rs17
-rw-r--r--crates/hir-def/src/item_scope.rs130
-rw-r--r--crates/hir-def/src/lib.rs21
-rw-r--r--crates/hir-def/src/nameres.rs1
-rw-r--r--crates/hir-def/src/nameres/collector.rs7
-rw-r--r--crates/hir-def/src/nameres/path_resolution.rs2
-rw-r--r--crates/hir-def/src/nameres/tests/incremental.rs2
-rw-r--r--crates/hir-def/src/per_ns.rs34
-rw-r--r--crates/hir-def/src/resolver.rs6
-rw-r--r--crates/ide-db/src/lib.rs3
11 files changed, 174 insertions, 67 deletions
diff --git a/crates/hir-def/src/find_path.rs b/crates/hir-def/src/find_path.rs
index 59c250d7506..234d3eaed56 100644
--- a/crates/hir-def/src/find_path.rs
+++ b/crates/hir-def/src/find_path.rs
@@ -1293,4 +1293,22 @@ pub mod prelude {
             "None",
         );
     }
+
+    #[test]
+    fn different_crate_renamed_through_dep() {
+        check_found_path(
+            r#"
+//- /main.rs crate:main deps:intermediate
+$0
+//- /intermediate.rs crate:intermediate deps:std
+pub extern crate std as std_renamed;
+//- /std.rs crate:std
+pub struct S;
+    "#,
+            "intermediate::std_renamed::S",
+            "intermediate::std_renamed::S",
+            "intermediate::std_renamed::S",
+            "intermediate::std_renamed::S",
+        );
+    }
 }
diff --git a/crates/hir-def/src/import_map.rs b/crates/hir-def/src/import_map.rs
index d742b2eef0a..5d7bb0b49d7 100644
--- a/crates/hir-def/src/import_map.rs
+++ b/crates/hir-def/src/import_map.rs
@@ -114,6 +114,9 @@ fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> FxIndexMap<ItemIn
 
         for (name, per_ns) in visible_items {
             for item in per_ns.iter_items() {
+                // FIXME: Not yet used, but will be once we handle doc(hidden) import sources
+                let is_doc_hidden = false;
+
                 let import_info = ImportInfo {
                     name: name.clone(),
                     container: module,
@@ -121,15 +124,17 @@ fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> FxIndexMap<ItemIn
                 };
 
                 match depth_map.entry(item) {
-                    Entry::Vacant(entry) => {
-                        entry.insert(depth);
-                    }
+                    Entry::Vacant(entry) => _ = entry.insert((depth, is_doc_hidden)),
                     Entry::Occupied(mut entry) => {
-                        if depth < *entry.get() {
-                            entry.insert(depth);
-                        } else {
+                        let &(occ_depth, occ_is_doc_hidden) = entry.get();
+                        // Prefer the one that is not doc(hidden),
+                        // Otherwise, if both have the same doc(hidden)-ness and the new path is shorter, prefer that one.
+                        let overwrite_entry = occ_is_doc_hidden && !is_doc_hidden
+                            || occ_is_doc_hidden == is_doc_hidden && depth < occ_depth;
+                        if !overwrite_entry {
                             continue;
                         }
+                        entry.insert((depth, is_doc_hidden));
                     }
                 }
 
diff --git a/crates/hir-def/src/item_scope.rs b/crates/hir-def/src/item_scope.rs
index 873accafb43..03fc5c3abde 100644
--- a/crates/hir-def/src/item_scope.rs
+++ b/crates/hir-def/src/item_scope.rs
@@ -6,6 +6,7 @@ use std::collections::hash_map::Entry;
 use base_db::CrateId;
 use hir_expand::{attrs::AttrId, db::ExpandDatabase, name::Name, AstId, MacroCallId};
 use itertools::Itertools;
+use la_arena::Idx;
 use once_cell::sync::Lazy;
 use profile::Count;
 use rustc_hash::{FxHashMap, FxHashSet};
@@ -32,15 +33,50 @@ pub struct PerNsGlobImports {
     macros: FxHashSet<(LocalModuleId, Name)>,
 }
 
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum ImportOrExternCrate {
+    Import(ImportId),
+    Glob(UseId),
+    ExternCrate(ExternCrateId),
+}
+
+impl ImportOrExternCrate {
+    pub fn into_import(self) -> Option<ImportId> {
+        match self {
+            ImportOrExternCrate::Import(it) => Some(it),
+            _ => None,
+        }
+    }
+
+    pub fn into_glob(self) -> Option<UseId> {
+        match self {
+            ImportOrExternCrate::Glob(it) => Some(it),
+            _ => None,
+        }
+    }
+}
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum ImportOrDef {
+    Import(ImportId),
+    ExternCrate(ExternCrateId),
+    Def(ModuleDefId),
+}
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub struct ImportId {
+    pub import: UseId,
+    pub idx: Idx<ast::UseTree>,
+}
+
 #[derive(Debug, Default, PartialEq, Eq)]
 pub struct ItemScope {
     _c: Count<Self>,
 
     /// Defs visible in this scope. This includes `declarations`, but also
     /// imports.
-    types: FxHashMap<Name, (ModuleDefId, Visibility)>,
-    values: FxHashMap<Name, (ModuleDefId, Visibility)>,
-    macros: FxHashMap<Name, (MacroId, Visibility)>,
+    types: FxHashMap<Name, (ModuleDefId, Visibility, Option<ImportOrExternCrate>)>,
+    values: FxHashMap<Name, (ModuleDefId, Visibility, Option<ImportId>)>,
+    macros: FxHashMap<Name, (MacroId, Visibility, Option<ImportId>)>,
     unresolved: FxHashSet<Name>,
 
     /// The defs declared in this scope. Each def has a single scope where it is
@@ -50,7 +86,14 @@ pub struct ItemScope {
     impls: Vec<ImplId>,
     unnamed_consts: Vec<ConstId>,
     /// Traits imported via `use Trait as _;`.
-    unnamed_trait_imports: FxHashMap<TraitId, Visibility>,
+    unnamed_trait_imports: FxHashMap<TraitId, (Visibility, Option<ImportId>)>,
+
+    // the resolutions of the imports of this scope
+    use_imports_types: FxHashMap<UseId, ImportOrDef>,
+    use_imports_values: FxHashMap<UseId, ImportOrDef>,
+    use_imports_macros: FxHashMap<UseId, ImportOrDef>,
+
+    use_decls: Vec<UseId>,
     extern_crate_decls: Vec<ExternCrateId>,
     /// Macros visible in current module in legacy textual scope
     ///
@@ -121,8 +164,7 @@ impl ItemScope {
     }
 
     pub fn use_decls(&self) -> impl Iterator<Item = UseId> + ExactSizeIterator + '_ {
-        // FIXME: to be implemented
-        std::iter::empty()
+        self.use_decls.iter().copied()
     }
 
     pub fn impls(&self) -> impl Iterator<Item = ImplId> + ExactSizeIterator + '_ {
@@ -132,13 +174,13 @@ impl ItemScope {
     pub fn values(
         &self,
     ) -> impl Iterator<Item = (ModuleDefId, Visibility)> + ExactSizeIterator + '_ {
-        self.values.values().copied()
+        self.values.values().copied().map(|(a, b, _)| (a, b))
     }
 
-    pub fn types(
+    pub(crate) fn types(
         &self,
     ) -> impl Iterator<Item = (ModuleDefId, Visibility)> + ExactSizeIterator + '_ {
-        self.types.values().copied()
+        self.types.values().copied().map(|(def, vis, _)| (def, vis))
     }
 
     pub fn unnamed_consts(&self) -> impl Iterator<Item = ConstId> + '_ {
@@ -165,33 +207,48 @@ impl ItemScope {
     }
 
     pub(crate) fn type_(&self, name: &Name) -> Option<(ModuleDefId, Visibility)> {
-        self.types.get(name).copied()
+        self.types.get(name).copied().map(|(a, b, _)| (a, b))
     }
 
     /// XXX: this is O(N) rather than O(1), try to not introduce new usages.
     pub(crate) fn name_of(&self, item: ItemInNs) -> Option<(&Name, Visibility)> {
-        let (def, mut iter) = match item {
-            ItemInNs::Macros(def) => {
-                return self.macros.iter().find_map(|(name, &(other_def, vis))| {
-                    (other_def == def).then_some((name, vis))
-                });
-            }
-            ItemInNs::Types(def) => (def, self.types.iter()),
-            ItemInNs::Values(def) => (def, self.values.iter()),
-        };
-        iter.find_map(|(name, &(other_def, vis))| (other_def == def).then_some((name, vis)))
+        match item {
+            ItemInNs::Macros(def) => self
+                .macros
+                .iter()
+                .find_map(|(name, &(other_def, vis, _))| (other_def == def).then_some((name, vis))),
+            ItemInNs::Types(def) => self
+                .types
+                .iter()
+                .find_map(|(name, &(other_def, vis, _))| (other_def == def).then_some((name, vis))),
+
+            ItemInNs::Values(def) => self
+                .values
+                .iter()
+                .find_map(|(name, &(other_def, vis, _))| (other_def == def).then_some((name, vis))),
+        }
     }
 
     pub(crate) fn traits(&self) -> impl Iterator<Item = TraitId> + '_ {
         self.types
             .values()
-            .filter_map(|&(def, _)| match def {
+            .filter_map(|&(def, _, _)| match def {
                 ModuleDefId::TraitId(t) => Some(t),
                 _ => None,
             })
             .chain(self.unnamed_trait_imports.keys().copied())
     }
 
+    pub(crate) fn resolutions(&self) -> impl Iterator<Item = (Option<Name>, PerNs)> + '_ {
+        self.entries().map(|(name, res)| (Some(name.clone()), res)).chain(
+            self.unnamed_trait_imports
+                .iter()
+                .map(|(tr, (vis, _))| (None, PerNs::types(ModuleDefId::TraitId(*tr), *vis))),
+        )
+    }
+}
+
+impl ItemScope {
     pub(crate) fn declare(&mut self, def: ModuleDefId) {
         self.declarations.push(def)
     }
@@ -278,11 +335,11 @@ impl ItemScope {
     }
 
     pub(crate) fn unnamed_trait_vis(&self, tr: TraitId) -> Option<Visibility> {
-        self.unnamed_trait_imports.get(&tr).copied()
+        self.unnamed_trait_imports.get(&tr).copied().map(|(a, _)| a)
     }
 
     pub(crate) fn push_unnamed_trait(&mut self, tr: TraitId, vis: Visibility) {
-        self.unnamed_trait_imports.insert(tr, vis);
+        self.unnamed_trait_imports.insert(tr, (vis, None));
     }
 
     pub(crate) fn push_res_with_import(
@@ -343,27 +400,18 @@ impl ItemScope {
         changed
     }
 
-    pub(crate) fn resolutions(&self) -> impl Iterator<Item = (Option<Name>, PerNs)> + '_ {
-        self.entries().map(|(name, res)| (Some(name.clone()), res)).chain(
-            self.unnamed_trait_imports
-                .iter()
-                .map(|(tr, vis)| (None, PerNs::types(ModuleDefId::TraitId(*tr), *vis))),
-        )
-    }
-
     /// Marks everything that is not a procedural macro as private to `this_module`.
     pub(crate) fn censor_non_proc_macros(&mut self, this_module: ModuleId) {
         self.types
             .values_mut()
-            .chain(self.values.values_mut())
+            .map(|(def, vis, _)| (def, vis))
+            .chain(self.values.values_mut().map(|(def, vis, _)| (def, vis)))
             .map(|(_, v)| v)
-            .chain(self.unnamed_trait_imports.values_mut())
+            .chain(self.unnamed_trait_imports.values_mut().map(|(vis, _)| vis))
             .for_each(|vis| *vis = Visibility::Module(this_module));
 
-        for (mac, vis) in self.macros.values_mut() {
-            if let MacroId::ProcMacroId(_) = mac {
-                // FIXME: Technically this is insufficient since reexports of proc macros are also
-                // forbidden. Practically nobody does that.
+        for (mac, vis, import) in self.macros.values_mut() {
+            if matches!(mac, MacroId::ProcMacroId(_) if import.is_none()) {
                 continue;
             }
 
@@ -415,10 +463,17 @@ impl ItemScope {
             attr_macros,
             derive_macros,
             extern_crate_decls,
+            use_decls,
+            use_imports_values,
+            use_imports_types,
+            use_imports_macros,
         } = self;
         types.shrink_to_fit();
         values.shrink_to_fit();
         macros.shrink_to_fit();
+        use_imports_types.shrink_to_fit();
+        use_imports_values.shrink_to_fit();
+        use_imports_macros.shrink_to_fit();
         unresolved.shrink_to_fit();
         declarations.shrink_to_fit();
         impls.shrink_to_fit();
@@ -428,6 +483,7 @@ impl ItemScope {
         attr_macros.shrink_to_fit();
         derive_macros.shrink_to_fit();
         extern_crate_decls.shrink_to_fit();
+        use_decls.shrink_to_fit();
     }
 }
 
diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs
index c40bbc0380e..3c0ed8c2e51 100644
--- a/crates/hir-def/src/lib.rs
+++ b/crates/hir-def/src/lib.rs
@@ -865,6 +865,7 @@ impl_from!(
     ConstId,
     FunctionId,
     TraitId,
+    TraitAliasId,
     TypeAliasId,
     MacroId(Macro2Id, MacroRulesId, ProcMacroId),
     ImplId,
@@ -873,6 +874,26 @@ impl_from!(
     for AttrDefId
 );
 
+impl TryFrom<ModuleDefId> for AttrDefId {
+    type Error = ();
+
+    fn try_from(value: ModuleDefId) -> Result<Self, Self::Error> {
+        match value {
+            ModuleDefId::ModuleId(it) => Ok(it.into()),
+            ModuleDefId::FunctionId(it) => Ok(it.into()),
+            ModuleDefId::AdtId(it) => Ok(it.into()),
+            ModuleDefId::EnumVariantId(it) => Ok(it.into()),
+            ModuleDefId::ConstId(it) => Ok(it.into()),
+            ModuleDefId::StaticId(it) => Ok(it.into()),
+            ModuleDefId::TraitId(it) => Ok(it.into()),
+            ModuleDefId::TypeAliasId(it) => Ok(it.into()),
+            ModuleDefId::TraitAliasId(id) => Ok(id.into()),
+            ModuleDefId::MacroId(id) => Ok(id.into()),
+            ModuleDefId::BuiltinType(_) => Err(()),
+        }
+    }
+}
+
 impl From<ItemContainerId> for AttrDefId {
     fn from(acid: ItemContainerId) -> Self {
         match acid {
diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs
index f93125e224d..f2110410980 100644
--- a/crates/hir-def/src/nameres.rs
+++ b/crates/hir-def/src/nameres.rs
@@ -108,6 +108,7 @@ pub struct DefMap {
     prelude: Option<(ModuleId, Option<UseId>)>,
     /// `macro_use` prelude that contains macros from `#[macro_use]`'d external crates. Note that
     /// this contains all kinds of macro, not just `macro_rules!` macro.
+    /// ExternCrateId being None implies it being imported from the general prelude import.
     macro_use_prelude: FxHashMap<Name, (MacroId, Option<ExternCrateId>)>,
 
     /// Tracks which custom derives are in scope for an item, to allow resolution of derive helper
diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs
index e3253404d49..b6658e4552c 100644
--- a/crates/hir-def/src/nameres/collector.rs
+++ b/crates/hir-def/src/nameres/collector.rs
@@ -33,7 +33,7 @@ use crate::{
     attr_macro_as_call_id,
     db::DefDatabase,
     derive_macro_as_call_id,
-    item_scope::{ImportType, PerNsGlobImports},
+    item_scope::{ImportOrExternCrate, ImportType, PerNsGlobImports},
     item_tree::{
         self, ExternCrate, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, ItemTreeNode,
         MacroCall, MacroDef, MacroRules, Mod, ModItem, ModKind, TreeId,
@@ -546,8 +546,8 @@ impl DefCollector<'_> {
             self.def_map.resolve_path(self.db, DefMap::ROOT, &path, BuiltinShadowMode::Other, None);
 
         match per_ns.types {
-            Some((ModuleDefId::ModuleId(m), _)) => {
-                self.def_map.prelude = Some((m, None));
+            Some((ModuleDefId::ModuleId(m), _, import)) => {
+                self.def_map.prelude = Some((m, import.and_then(ImportOrExternCrate::into_glob)));
             }
             types => {
                 tracing::debug!(
@@ -714,7 +714,6 @@ impl DefCollector<'_> {
         &mut self,
         krate: CrateId,
         names: Option<Vec<Name>>,
-
         extern_crate: Option<ExternCrateId>,
     ) {
         let def_map = self.db.crate_def_map(krate);
diff --git a/crates/hir-def/src/nameres/path_resolution.rs b/crates/hir-def/src/nameres/path_resolution.rs
index 64cdbdce770..fc296e1e588 100644
--- a/crates/hir-def/src/nameres/path_resolution.rs
+++ b/crates/hir-def/src/nameres/path_resolution.rs
@@ -65,7 +65,7 @@ impl PerNs {
         db: &dyn DefDatabase,
         expected: Option<MacroSubNs>,
     ) -> Self {
-        self.macros = self.macros.filter(|&(id, _)| {
+        self.macros = self.macros.filter(|&(id, _, _)| {
             let this = MacroSubNs::from_id(db, id);
             sub_namespace_match(Some(this), expected)
         });
diff --git a/crates/hir-def/src/nameres/tests/incremental.rs b/crates/hir-def/src/nameres/tests/incremental.rs
index 40d3a16540d..4a86f88e57a 100644
--- a/crates/hir-def/src/nameres/tests/incremental.rs
+++ b/crates/hir-def/src/nameres/tests/incremental.rs
@@ -212,7 +212,7 @@ pub type Ty = ();
             }
 
             for (_, res) in module_data.scope.resolutions() {
-                match res.values.or(res.types).unwrap().0 {
+                match res.values.map(|(a, _, _)| a).or(res.types.map(|(a, _, _)| a)).unwrap() {
                     ModuleDefId::FunctionId(f) => _ = db.function_data(f),
                     ModuleDefId::AdtId(adt) => match adt {
                         AdtId::StructId(it) => _ = db.struct_data(it),
diff --git a/crates/hir-def/src/per_ns.rs b/crates/hir-def/src/per_ns.rs
index 2bc1f8e926e..f32a97d1a3a 100644
--- a/crates/hir-def/src/per_ns.rs
+++ b/crates/hir-def/src/per_ns.rs
@@ -3,13 +3,17 @@
 //!
 //! `PerNs` (per namespace) captures this.
 
-use crate::{item_scope::ItemInNs, visibility::Visibility, MacroId, ModuleDefId};
+use crate::{
+    item_scope::{ImportId, ImportOrExternCrate, ItemInNs},
+    visibility::Visibility,
+    MacroId, ModuleDefId,
+};
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub struct PerNs {
-    pub types: Option<(ModuleDefId, Visibility)>,
-    pub values: Option<(ModuleDefId, Visibility)>,
-    pub macros: Option<(MacroId, Visibility)>,
+    pub types: Option<(ModuleDefId, Visibility, Option<ImportOrExternCrate>)>,
+    pub values: Option<(ModuleDefId, Visibility, Option<ImportId>)>,
+    pub macros: Option<(MacroId, Visibility, Option<ImportId>)>,
 }
 
 impl Default for PerNs {
@@ -24,19 +28,19 @@ impl PerNs {
     }
 
     pub fn values(t: ModuleDefId, v: Visibility) -> PerNs {
-        PerNs { types: None, values: Some((t, v)), macros: None }
+        PerNs { types: None, values: Some((t, v, None)), macros: None }
     }
 
     pub fn types(t: ModuleDefId, v: Visibility) -> PerNs {
-        PerNs { types: Some((t, v)), values: None, macros: None }
+        PerNs { types: Some((t, v, None)), values: None, macros: None }
     }
 
     pub fn both(types: ModuleDefId, values: ModuleDefId, v: Visibility) -> PerNs {
-        PerNs { types: Some((types, v)), values: Some((values, v)), macros: None }
+        PerNs { types: Some((types, v, None)), values: Some((values, v, None)), macros: None }
     }
 
     pub fn macros(macro_: MacroId, v: Visibility) -> PerNs {
-        PerNs { types: None, values: None, macros: Some((macro_, v)) }
+        PerNs { types: None, values: None, macros: Some((macro_, v, None)) }
     }
 
     pub fn is_none(&self) -> bool {
@@ -52,7 +56,7 @@ impl PerNs {
     }
 
     pub fn take_types_vis(self) -> Option<(ModuleDefId, Visibility)> {
-        self.types
+        self.types.map(|(a, b, _)| (a, b))
     }
 
     pub fn take_values(self) -> Option<ModuleDefId> {
@@ -66,17 +70,17 @@ impl PerNs {
     pub fn filter_visibility(self, mut f: impl FnMut(Visibility) -> bool) -> PerNs {
         let _p = profile::span("PerNs::filter_visibility");
         PerNs {
-            types: self.types.filter(|(_, v)| f(*v)),
-            values: self.values.filter(|(_, v)| f(*v)),
-            macros: self.macros.filter(|(_, v)| f(*v)),
+            types: self.types.filter(|&(_, v, _)| f(v)),
+            values: self.values.filter(|&(_, v, _)| f(v)),
+            macros: self.macros.filter(|&(_, v, _)| f(v)),
         }
     }
 
     pub fn with_visibility(self, vis: Visibility) -> PerNs {
         PerNs {
-            types: self.types.map(|(it, _)| (it, vis)),
-            values: self.values.map(|(it, _)| (it, vis)),
-            macros: self.macros.map(|(it, _)| (it, vis)),
+            types: self.types.map(|(it, _, c)| (it, vis, c)),
+            values: self.values.map(|(it, _, c)| (it, vis, c)),
+            macros: self.macros.map(|(it, _, import)| (it, vis, import)),
         }
     }
 
diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs
index 17a1bf50b5e..28ab0f8f6ee 100644
--- a/crates/hir-def/src/resolver.rs
+++ b/crates/hir-def/src/resolver.rs
@@ -864,13 +864,13 @@ impl ScopeNames {
         }
     }
     fn add_per_ns(&mut self, name: &Name, def: PerNs) {
-        if let &Some((ty, _)) = &def.types {
+        if let &Some((ty, _, _)) = &def.types {
             self.add(name, ScopeDef::ModuleDef(ty))
         }
-        if let &Some((def, _)) = &def.values {
+        if let &Some((def, _, _)) = &def.values {
             self.add(name, ScopeDef::ModuleDef(def))
         }
-        if let &Some((mac, _)) = &def.macros {
+        if let &Some((mac, _, _)) = &def.macros {
             self.add(name, ScopeDef::ModuleDef(ModuleDefId::MacroId(mac)))
         }
         if def.is_none() {
diff --git a/crates/ide-db/src/lib.rs b/crates/ide-db/src/lib.rs
index f27ed485d81..ac3511ba47b 100644
--- a/crates/ide-db/src/lib.rs
+++ b/crates/ide-db/src/lib.rs
@@ -94,18 +94,21 @@ impl fmt::Debug for RootDatabase {
 }
 
 impl Upcast<dyn ExpandDatabase> for RootDatabase {
+    #[inline]
     fn upcast(&self) -> &(dyn ExpandDatabase + 'static) {
         &*self
     }
 }
 
 impl Upcast<dyn DefDatabase> for RootDatabase {
+    #[inline]
     fn upcast(&self) -> &(dyn DefDatabase + 'static) {
         &*self
     }
 }
 
 impl Upcast<dyn HirDatabase> for RootDatabase {
+    #[inline]
     fn upcast(&self) -> &(dyn HirDatabase + 'static) {
         &*self
     }