Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/lang_item.rs')
-rw-r--r--crates/hir-def/src/lang_item.rs187
1 files changed, 101 insertions, 86 deletions
diff --git a/crates/hir-def/src/lang_item.rs b/crates/hir-def/src/lang_item.rs
index 5431ec9679..51a833b5f1 100644
--- a/crates/hir-def/src/lang_item.rs
+++ b/crates/hir-def/src/lang_item.rs
@@ -83,104 +83,99 @@ impl LangItemTarget {
}
}
-#[derive(Default, Debug, Clone, PartialEq, Eq)]
-pub struct LangItems {
- items: FxHashMap<LangItem, LangItemTarget>,
-}
+/// Salsa query. This will look for lang items in a specific crate.
+#[salsa_macros::tracked(return_ref)]
+pub fn crate_lang_items(db: &dyn DefDatabase, krate: Crate) -> Option<Box<LangItems>> {
+ let _p = tracing::info_span!("crate_lang_items_query").entered();
-impl LangItems {
- pub fn target(&self, item: LangItem) -> Option<LangItemTarget> {
- self.items.get(&item).copied()
- }
+ let mut lang_items = LangItems::default();
- /// Salsa query. This will look for lang items in a specific crate.
- pub(crate) fn crate_lang_items_query(
- db: &dyn DefDatabase,
- krate: Crate,
- ) -> Option<Arc<LangItems>> {
- let _p = tracing::info_span!("crate_lang_items_query").entered();
-
- let mut lang_items = LangItems::default();
+ let crate_def_map = db.crate_def_map(krate);
- let crate_def_map = db.crate_def_map(krate);
+ for (_, module_data) in crate_def_map.modules() {
+ for impl_def in module_data.scope.impls() {
+ lang_items.collect_lang_item(db, impl_def, LangItemTarget::ImplDef);
+ for &(_, assoc) in db.impl_items(impl_def).items.iter() {
+ match assoc {
+ AssocItemId::FunctionId(f) => {
+ lang_items.collect_lang_item(db, f, LangItemTarget::Function)
+ }
+ AssocItemId::TypeAliasId(t) => {
+ lang_items.collect_lang_item(db, t, LangItemTarget::TypeAlias)
+ }
+ AssocItemId::ConstId(_) => (),
+ }
+ }
+ }
- for (_, module_data) in crate_def_map.modules() {
- for impl_def in module_data.scope.impls() {
- lang_items.collect_lang_item(db, impl_def, LangItemTarget::ImplDef);
- for &(_, assoc) in db.impl_items(impl_def).items.iter() {
- match assoc {
+ for def in module_data.scope.declarations() {
+ match def {
+ ModuleDefId::TraitId(trait_) => {
+ lang_items.collect_lang_item(db, trait_, LangItemTarget::Trait);
+ db.trait_items(trait_).items.iter().for_each(|&(_, assoc_id)| match assoc_id {
AssocItemId::FunctionId(f) => {
- lang_items.collect_lang_item(db, f, LangItemTarget::Function)
+ lang_items.collect_lang_item(db, f, LangItemTarget::Function);
}
- AssocItemId::TypeAliasId(t) => {
- lang_items.collect_lang_item(db, t, LangItemTarget::TypeAlias)
+ AssocItemId::TypeAliasId(alias) => {
+ lang_items.collect_lang_item(db, alias, LangItemTarget::TypeAlias)
}
- AssocItemId::ConstId(_) => (),
- }
+ AssocItemId::ConstId(_) => {}
+ });
}
- }
-
- for def in module_data.scope.declarations() {
- match def {
- ModuleDefId::TraitId(trait_) => {
- lang_items.collect_lang_item(db, trait_, LangItemTarget::Trait);
- db.trait_items(trait_).items.iter().for_each(
- |&(_, assoc_id)| match assoc_id {
- AssocItemId::FunctionId(f) => {
- lang_items.collect_lang_item(db, f, LangItemTarget::Function);
- }
- AssocItemId::TypeAliasId(alias) => lang_items.collect_lang_item(
- db,
- alias,
- LangItemTarget::TypeAlias,
- ),
- AssocItemId::ConstId(_) => {}
- },
- );
- }
- ModuleDefId::AdtId(AdtId::EnumId(e)) => {
- lang_items.collect_lang_item(db, e, LangItemTarget::EnumId);
- db.enum_variants(e).variants.iter().for_each(|&(id, _)| {
- lang_items.collect_lang_item(db, id, LangItemTarget::EnumVariant);
- });
- }
- ModuleDefId::AdtId(AdtId::StructId(s)) => {
- lang_items.collect_lang_item(db, s, LangItemTarget::Struct);
- }
- ModuleDefId::AdtId(AdtId::UnionId(u)) => {
- lang_items.collect_lang_item(db, u, LangItemTarget::Union);
- }
- ModuleDefId::FunctionId(f) => {
- lang_items.collect_lang_item(db, f, LangItemTarget::Function);
- }
- ModuleDefId::StaticId(s) => {
- lang_items.collect_lang_item(db, s, LangItemTarget::Static);
- }
- ModuleDefId::TypeAliasId(t) => {
- lang_items.collect_lang_item(db, t, LangItemTarget::TypeAlias);
- }
- _ => {}
+ ModuleDefId::AdtId(AdtId::EnumId(e)) => {
+ lang_items.collect_lang_item(db, e, LangItemTarget::EnumId);
+ db.enum_variants(e).variants.iter().for_each(|&(id, _)| {
+ lang_items.collect_lang_item(db, id, LangItemTarget::EnumVariant);
+ });
+ }
+ ModuleDefId::AdtId(AdtId::StructId(s)) => {
+ lang_items.collect_lang_item(db, s, LangItemTarget::Struct);
+ }
+ ModuleDefId::AdtId(AdtId::UnionId(u)) => {
+ lang_items.collect_lang_item(db, u, LangItemTarget::Union);
}
+ ModuleDefId::FunctionId(f) => {
+ lang_items.collect_lang_item(db, f, LangItemTarget::Function);
+ }
+ ModuleDefId::StaticId(s) => {
+ lang_items.collect_lang_item(db, s, LangItemTarget::Static);
+ }
+ ModuleDefId::TypeAliasId(t) => {
+ lang_items.collect_lang_item(db, t, LangItemTarget::TypeAlias);
+ }
+ _ => {}
}
}
+ }
- if lang_items.items.is_empty() { None } else { Some(Arc::new(lang_items)) }
+ if lang_items.items.is_empty() { None } else { Some(Box::new(lang_items)) }
+}
+
+/// Salsa query. Look for a lang item, starting from the specified crate and recursively
+/// traversing its dependencies.
+#[salsa_macros::tracked]
+pub fn lang_item(
+ db: &dyn DefDatabase,
+ start_crate: Crate,
+ item: LangItem,
+) -> Option<LangItemTarget> {
+ let _p = tracing::info_span!("lang_item_query").entered();
+ if let Some(target) =
+ crate_lang_items(db, start_crate).as_ref().and_then(|it| it.items.get(&item).copied())
+ {
+ return Some(target);
}
+ start_crate.data(db).dependencies.iter().find_map(|dep| lang_item(db, dep.crate_id, item))
+}
- /// Salsa query. Look for a lang item, starting from the specified crate and recursively
- /// traversing its dependencies.
- pub(crate) fn lang_item_query(
- db: &dyn DefDatabase,
- start_crate: Crate,
- item: LangItem,
- ) -> Option<LangItemTarget> {
- let _p = tracing::info_span!("lang_item_query").entered();
- if let Some(target) =
- db.crate_lang_items(start_crate).and_then(|it| it.items.get(&item).copied())
- {
- return Some(target);
- }
- start_crate.data(db).dependencies.iter().find_map(|dep| db.lang_item(dep.crate_id, item))
+#[derive(Default, Debug, Clone, PartialEq, Eq)]
+pub struct LangItems {
+ items: FxHashMap<LangItem, LangItemTarget>,
+}
+
+impl LangItems {
+ pub fn target(&self, item: LangItem) -> Option<LangItemTarget> {
+ self.items.get(&item).copied()
}
fn collect_lang_item<T>(
@@ -269,18 +264,38 @@ macro_rules! language_item_table {
}
impl LangItem {
+ pub fn resolve_function(self, db: &dyn DefDatabase, start_crate: Crate) -> Option<FunctionId> {
+ lang_item(db, start_crate, self).and_then(|t| t.as_function())
+ }
+
+ pub fn resolve_trait(self, db: &dyn DefDatabase, start_crate: Crate) -> Option<TraitId> {
+ lang_item(db, start_crate, self).and_then(|t| t.as_trait())
+ }
+
+ pub fn resolve_enum(self, db: &dyn DefDatabase, start_crate: Crate) -> Option<EnumId> {
+ lang_item(db, start_crate, self).and_then(|t| t.as_enum())
+ }
+
+ pub fn resolve_type_alias(
+ self,
+ db: &dyn DefDatabase,
+ start_crate: Crate,
+ ) -> Option<TypeAliasId> {
+ lang_item(db, start_crate, self).and_then(|t| t.as_type_alias())
+ }
+
/// Opposite of [`LangItem::name`]
pub fn from_name(name: &hir_expand::name::Name) -> Option<Self> {
Self::from_symbol(name.symbol())
}
pub fn path(&self, db: &dyn DefDatabase, start_crate: Crate) -> Option<Path> {
- let t = db.lang_item(start_crate, *self)?;
+ let t = lang_item(db, start_crate, *self)?;
Some(Path::LangItem(t, None))
}
pub fn ty_rel_path(&self, db: &dyn DefDatabase, start_crate: Crate, seg: Name) -> Option<Path> {
- let t = db.lang_item(start_crate, *self)?;
+ let t = lang_item(db, start_crate, *self)?;
Some(Path::LangItem(t, Some(seg)))
}
}